https://www.pagetable.com/?p=1520 Skip to content pagetable.com Some Assembly Required [ ] Search Menu * About * Search Commodore's Assemblers: Part 1: MOS Cross-Assembler 2021-05-152021-05-15 by Michael Steil In the series about the assemblers Commodore used for developing the ROMs of their 8-bit computers, this article covers the 1975 "MOS Cross-Assembler", which was available for various mainfraimes of the era. [cross-asse] Series Overview * Part 0: Overview * Part 1: MOS Cross-Assembler - this article * Part 2: MOS Resident Assembler [coming soon] * Part 3: BSO CR6502/11 [coming soon] * Part 4: HCD65 [coming soon] * Part 5: Commodore 6502 ASM [coming soon] [cbmasm_his] History With the introduction of the 6502 in 1975, MOS Technology, Inc. also released two assemblers for the new architecture: the " Cross-Assembler", available for various mainframes and minicomputers, and the "Resident Assembler", running on natively on 6502 systems. According to the master's thesis A Cross-Assembler/Simulator for a Microprocessor-Based Industrial Controller, the original MOS Cross-Assembler, together with a simulator, was implemented by the student Robert E. Blanton at the University of Illinois at Urbana-Champaign. It was written in FORTRAN and used a 6-bit (i.e. all uppercase) character encoding. On the university's CDC Cyber 175 system, it required 120K (!) 60-bit words of memory to run and had "generally acceptable" response times. The Resident Assembler (part 2 of the series) was then developed using the Cross-Assembler, and designed to be compatible in that it understood the same source format, with the same math features and the same directives and options. This way, MOS defined the basic format supported by all future Commodore assemblers. Platforms Today, you would expect a cross-assembler to run on Linux, Windows or Mac. But these were different times: When the 6502 was released, microcomputers were just appearing - and the 6502 was a part of this shift - and even the first fridge-sized minicomputers like the PDP series had only been introduced 10 years earlier. Most companies that used computers at the time used terminals that dialed into mainframes hosted in computing centers. And the market was very fragmented. The 6502 Programming Manual (6500-50A) states: The Cross Assembler is available on various time share systems or for batch use on the user's system. According to the 6502 Cross Assembler Manual (6500-60P), the supported platforms as of August 1975 were: * GE Timesharing, running on GE/Honeywell mainframes * National CSS time-sharing, running VP/CSS on IBM System/360 and System/370 mainframes And the 1975 MOS Technology marketing brochure: Current plans involve having the software available on several of the more popular Time Sharing services. In addition, it will be available for deck sales. Batch decks for the CDC, IBM, and PDP-11 class machines are available and we will support several other popular mini and major computer systems in the near future. The 1975 MCS6500 Microprocessor Software Support brochure shows the Cross-Assembler running on the United Computing Systems (UCS) time-sharing service. This dissertation shows that the Iowa State University ran version 4 of the Cross-Assembler locally on an IBM 360/370. Basic Syntax Back then, not all computer systems used the ASCII encoding, and some computers didn't even support lower case. The encoding of source files is therefore specific to the platform the Cross-Assembler runs on, and only uppercase characters were allowed. Here is an example from the manual: ; ; 650X CROSS ASSEMBLER SAMPLE PROGRAM. ; *=$C000 DEFINE ORIGIN. LDX #$FF SET UP STACK. TXS LOAD STACK POINTER. LDA #$F0 LOAD A WITH HEX F0. STA ASAVE SAVE A IN ASAVE. ; ; ALLOCATE SAVE AREA. ; *=$0000 ASAVE *=* .END * Lines starting with ; are comments and will be ignored. * Labels start at the first column, everything else is indented. * Comments may follow the operand or the operand-less mnemonic. No ; is necessary. * The Cross-Assembler uses the *= syntax to define the current assembly address. The rule about the start columns of labels and assembly statements is actually more relaxed, as this very compressed example from the C64 KERNAL shows: ;COMMAND SERIAL BUS DEVICE TO LISTEN ; LISTN ORA #$20 ;MAKE A LISTEN ADR JSR RSP232 ;PROTECT SELF FROM RS232 NMI'S LIST1 PHA Since all mnemos and register names are reserved keywords and cannot be used for labels, the assembler does not enforce indenting for assembly statement. The JSR RSP232 starting at the first column is legal. In fact, even labels may be indented. This example prepends comments after statements with ;, which is legal because the assembler ignores everything after the statement anyway. If you want to go for maximum readability (and don't care about the size of the source), you could also indent the above example like this: ; COMMAND SERIAL BUS DEVICE TO LISTEN ; LISTN ORA #$20 ; MAKE A LISTEN ADR JSR RSP232 ; PROTECT SELF FROM RS232 NMI'S LIST1 PHA Labels can be up to 6 characters in length, so one could use 7 character indents for statements so that they always line up. That's also how the LST output is formatted, which will be described later. Assembly Statements The accepted syntax of assembly statements matches the one in the 6502 Programming Manual. This includes the syntax for statements that take the accumulator as the argument: ASL A LSR A ROL A ROR A Modern assemblers usually allow omitting the A; the Cross-Assembler does not. One additional feature is an alternative syntax to the indirect, y-indexed addressing mode. In addition to LDA (PNT),Y the following syntax is accepted: LDA (PNT)Y Expressions Operands of assembly statements can use hexadecimal ($), octal (@), binary (%) and decimal (no prefix) constants. Mathematical expressions using +, -, * and / are possible, but they are always evaluated left-to-right with no operator precedence and no parenthetical grouping. Character/string literals are prefixed with '. Directives The Cross-Assembler understands the following directives: * .BYTE: store one or more bytes * .WORD: store one or more words (little endian) * .DBYTE: store one or more words (big endian) * .PAGE: optionally set a section title, and cause an LST page break * .SKIP: insert a number of blank lines into the LST * .END: stop assembly; not required but suggested at end of file * .OPT: set or clear a list of options + XREF - NOXREF: add a cross-reference to the end of the LST + ERRORS - NOERRORS: write errors into separate file + COUNT/CNT - NOCOUNT: add mnemo statistics to the end of the LST + LIST - NOLIST: enable LST output + MEMORY - NOMEMORY: enable writing object file + GENERATE - NOGENERATE: verbose printing of character strings in the LST Only the first three characters after the period are actually checked. LST File Like most development tools from the 1970s, the assembler can create a so-called listing file (suggested file extension .LST) during assembly that shows the source and the generated bytes side-by-side and is meant to be printed on paper. Here is a example from the manual: CARD # LOC CODE CARD 1 CR=15 2 LF=12 3 ; LOW CORE DATA AREAS 4 0000 E7 06 TEMTBL .WORD G3TEM, G1TEM 5 0002 E7 05 6 GROUP=B10 7 0004 00 THI .BYTE 0 8 0005 00 TLO .BYTE 0 9 0006 00 00 00 3PER .WORD 0 ***** ERROR ** LABEL DOESN'T BEGIN WITH ALPHABETIC CHARACTER - NEAR COLUMN 1 10 0009 B1 0E NEXT LDA (SAVIL)Y [...] 269 07C9 C9 3B CMP #'; 270 07CB 00 00 BEQ DONE ***** ERROR ** UNDEFINED SYMBOL - NEAR COLUMN 18 280 .END END OF MOS/TECHNOLOGY 650X ASSEMBLY VERSION 4 NUMBER OF ERRORS = 2, NUMBER OF WARNINGS = 0 The first column (CARD #) is the line number in the source. The LOC field is the memory address, which is followed by the output bytes (CODE) and the source line (CARD), which the assembler re-indented for readability. The CARD nomenclature stems from 1960s mainframes, where each line of text was represented by one punch card. Error messages are shown as extra lines after the line that caused the error. Note that the assembler will keep working through the file no matter what, and will output placeholder bytes for lines with errors. The original LST printout of the KIM-1 ROM, which was part of the user manual, is a real-world example of a 1200-line LST file, with the symbol table and the mnemo statistics (.OPT COUNT) at the end. OBJ File The main output of the assembler is the binary program, which is in the form of a so-called "interface file" with a suggested file extension of .OBJ. The diverse set of platforms that the Cross-Assembler ran on all had different word sizes, and many of them measured memory only in words and did not even have a concept of (8-bit) "bytes". Therefore, the assembler could not output a binary file, but instead wrote a portable, hex-encoded text file, like this: ;18E500A200A0DC60A228A01960B00786D684D3206CE5A6D6A4D3600D8C ;18E51820A0E5A9008D910285CFA9488D8F02A9EB8D9002A90A8D890C62 [...] ;06FFFA43FEE2FC48FF0665 ;0001200021 Every line consists of the following characters: * ;: first character of each record * 2 chars: number of data bytes to follow * 4 chars: load address of first byte of line * 2 chars (repeated): data byte * 4 chars: checksum The last line is * ;00: identifier for last line * 4 chars: number of preceding lines * 4 chars: checksum The checksum is calculated by adding all preceding bytes of the line together. This text-only file is platform-independent and can easily be transferred between different computer systems, and e.g. downloaded from a time-sharing system in order to write it to an EPROM. Use at Commodore The Cross-Assembler was used at MOS to create the very first 6502 code, like the KIM-1 ROM (shown above), or the TIM ROM (MCS6530-004). A large amount of the original Commodore source code has been preserved, and all code before 1984 is in a format very similar to the original MOS definition supported by both the Cross-Assembler and the Resident Assembler. So at first sight, it is not so clear which assembler Commodore used for developing ROMs of the PET, VIC-20 etc. and the disk drives. The next article in the series will discuss this topic further. Categories 6502, Commodore Post navigation Commodore's Assemblers: Overview 1 thought on "Commodore's Assemblers: Part 1: MOS Cross-Assembler" 1. Mirko 2021-05-15 at 10:52 | Reply Thanks for the reconstruction of such a brilliant moment in computing history. Leave a Comment Cancel reply [ ] [ ] [ ] [ ] [ ] [ ] [ ] Comment[ ] Name[ ] Email [ ] Website [ ] [Post Comment] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] This site uses Akismet to reduce spam. Learn how your comment data is processed. Twitter: @pagetable Mastodon: @pagetable@mastodon.social Categories 6502 Amiga Apple Archeology BASIC Bildschirmtext C64 C128 Commodore Commodore Peripheral Bus Digital Video DOS Final Cartridge III Floppy Disks Game Boy GEOS GitHub Hacks Hardware KERNAL Literature Operating Systems PET Presentation Puzzle SCUMM Security Tapes Teardown TED Tricks Trivia Uncategorized VIC-20 Virtualization Whines X16 x86 Xbox Archives Archives [Select Month ] Meta * Log in * Entries RSS * Comments RSS * WordPress.org (c) 2021 pagetable.com * Powered by GeneratePress