MP-assembler
What is it?
MP-Assembler is an assembler to be used on the PC to assemble source code for the 6502, its compatible successors, and other CPUs. MP stands for "Multi Processor": At the moment it can assemble 6502, 65C02, 65816, 6800, 6809, 8088, TMS7000, Z80 and My TTL CPU opcode. The special feature of this assembler is that you can mix all opcodes in one and the same file This comes in handy when assembling programs for the C128 (6502 and Z80) and the MMF-9000 (6502 and 6809).Remark: I'm thinking about splitting it up in separate assemblers. It does make sense combining 6502 plus Z80, Commodore 128, and 6502 plus 6809, Commodore SuperPET, but for the rest, no. We'll see.
The story
Today a lot of assemblers exist for the 6502, Z80 etc. and each claims to be better than all the other ones. But when I started to write this one in 1988, there wasn't one available as free/shareware on the PC, AFAIK. There were some available for the C64 but here I encountered a problem: I wasn't able to handle large source codes because the C64 simply lacked the needed memory. At that time I already was thinking about replacing the drive of the 1541 with an hard disk and thus a big change of the original system ROM was needed. Much more memory and a bigger screen made me to decide not only to use a PC instead but also to write my own assembler.The used syntax is based in the first place on the assembler Hypra-Ass for the Commodore 64, published in the German Magazine 64'er in october 1984. Why? I simply didn't know another assemble, so why not? But in the meanwhile I accepted some syntax used by other assemblers as well.
I don't think my assembler is better the other ones. I used to say: "It has one major advantage: you get the source code with it! So if you don't like or miss certain features, you simply change them or add ones of your own.". But nowadays most assemblers are open source. Knowing the assembler through and through the advantage for me is that I know where and how to change and/or add things more quickly.
My assembler is a multi pass assembler. My assembler needs at least three passes. Please have a look at the next example:
.eq L1 = L2 + 5 .eq L2 = L3 + 8 .eq L3 = 18At the first pass L1, L2 and L3 are known but L1 and L2 cannot be evaluated because the value of L3 for L2 is unknown at that moment and the value of L2 for L1. At the next pass L2 can be calculated but not L1 yet. At the third pass L1 can be calculated as well. And a fourth pass is needed because now we are sure everything should be known. But if you expand the above example with L4, L5 and L6, at least seven passes are needed.
How does my assembler know that it needs more passes? It counts all errors encountered during a pass. Not being able to calculate the value for L2 is such an error. At the end of the first pass there are at least two errors. After the next pas it will be at least one. A decreased number of errors is valid reason enough to continue. The moment the number of errors is the same as the previous pass, that's why the very last pass is for, the assembler knows nothing can be done anymore and it stops assembling.
There exist two and even one pass assemblers but they are limited or IMHO they use one or another trick. I just kept it simple because a speedy computer will undo the disadvantages of more passes.
Last thing: I started writing this assembler using Turbo Pascal 3, went throug version 4, 5, 5.5, 6 and 7 and then I switched to Free Pascal Compiler. But some time ago I decided that it should be able to run on old machines as well and so I decided to go back to TP7.
Using the assembler
Usage: MPASSEMThe filename is mandatory. The extension like ".A65", ".Z80", ".ASM", etc. may be omitted but then the assembler will look for the first file having a known extension. If you have two files with the same name but different extensions, you run the risk that the wrong one is picked.
.a09 = Motorola 6809 .a65 = 6502 and equivalents .a68 = Motorola 6800, 6802 .a86 = Intel 8086/8088 .i80 = Intel 8080 .i85 = Intel 8085 .i86 = Intel 8086/8088, created by my Pascal compiler .tms = Texas Intruments TMS7000 series .ttl = my own TTL-CPU computer .z80 = Zilog Z80
The assembler files
The only two things the assembler asks from you is a begin and an end mark. Normally that would be ".ba" and ".en" but I started to support some directives used by other processors as well. For example, that would be "aorg" and "end' for the TMS7000. For the rest you are absolutely free to write it in the way you want. You can define more then one begin address but be warned: it is your own responsibility to take care of not overwriting previous assembled code!To help you to streamline your application you have a lot of compiler directives at your disposal:
.ap Filename = APpend a file to be assembled as well .as $xxxx $yyyyy = only ASsemble the given range .ba $xxxx = Begin Address of the code or data. More then one .ba may be used. .by [$]aa, [$]bb, [$]cc..... .by label1, label2..... = define a number of BYtes. You can use fixed values as well as labels or text .co This is comment = COmment to be displayed on the screen during the last pass .dw $xxxxxxxx = define a number of Double Words .ec = Enable Comment the in final super file for debugging .ei = End If: end of conditional programming .el = ELse: part of conditional programming .en = ENd of file. All text, code or data behind this mark will be ignored. .eq OwnLabel1 = $xx .eq OwnLabel2 = $xxxx .eq OwnLabel3 = OwnLabel2 + 1 = EQuals, define your own label. Values can be changed. .fb [$]xx, [$]yy .fb "c", [$]yy .fb label, [$]yy = Fill Byte: fill a range of length [$]yy with the same byte. A character, a fixed value or a label can be used as input. .fd [$]xxxxxxxx, [$]yy .fd "c", [$]yy .fd label, [$]yy = Fill Double word. .fi Filename = use a binary FIle as base for your own binary. Can be used to write patches over original binaries. .fu [$]xx,$yyyy = fill the buffer with a byte up to a given address .fw [$]xxxx, [$]yy .fw "cd", [$]yy .fw label, [$]yy = Fill Word. .ie = If Else: part of conditional programming .if label = IF: start of conditional programming. .ma Name = define a MAcro. .me = Macro End .paI'm working on a Pascal Compiler that uses this assembler to generate the executables. This can mean that I implement features and directives that are not mentioned yet in this document.= same as PAth in MS-DOS .p = processor type, this enables you to use multiple processors in one file p6502 p6800 including 6802 and equivalent types p6809 p8080 p8085 p8086 pTMS TMS7000 series pTTL my own TTL-CPU pZ80 .rb $aaaa = Re-address Begin. Following code will be assembled as if it was situated at address $aaaa. .re = Re-address End .ta = translate given text to ASCII (default) .tp = translate given text to PETSCII .tw "This is 'TEXT'" = TeXt, first char+$80 (for Commodore) .tx "This is 'TEXT'" .tx 'This is "TEXT"' = TeXt .ty "This is 'TEXT'" = TeXt, last char+$80 (for Commodore) .tz "This is 'TEXT'" = TeXt, first and last char+$80 (for Commodore) .uf
= Use File, include a file at this point .uu filename = Use external Unit as source for the used macros .wo $aaaa, $bbbb, $cccc..... .wo label1, label2..... = define a range of WOrds. ; Here you can place comments = remark /* here you can place several lines of comment */ = speaks for itself IMHO org $xxxx = begin address, same as .ba
The produced files
.BIN = binary to be used for programming EPROMs etc. .LST = text file with complete listing of statements and resulting code 'mp-asm.log' = log file
Example
Remark: most browsers aren't familiar with the A65 extension and will ask you whether to open or save it. If you download this example, you can assemble it with "MPASM test6580.a65".C000.asm is a very small but working code. It writes the character 'A' in the top-left corner of your C64 screen. ".ba $C000" means that the program starts at $C000 / 49152. The PRG should be loaded on a C64 with LOAD "C000",8,1. SYS 49152 will start the program.
Warning: be aware of the space in front of the opcodes! If there isn't any form of white space in front of an opcode, the assembler will treat it as a label. And as it won't recognise the operand as opcode, the assembler will end with an error.
C001.asm will display the alphabet on the screen. Notice the place of label L1. Also notice that, although it is quite small, the program is hardly readable.
C002.asm is the same program but made more readable. The most important difference are the lines with comment. How small your program is, comment it! If it isn't for your self, do it for others.
test6580.asm is a test file used by me to test almost all features of the assembler. It also explains the use of most directives. If you have questions, just drop me an email.
Texas Instruments TMS7000
Jaak Bartok, Jaaks Electronics & vintage Workplace(s),and Fred Jan Kraan, Oh no, not another computer museum! are working on some projects that involve several variants of the TMS7000. Their problem: they had no assembler that supported Texas Instruments' original source statement format. Having done me several favours, I decided to return them mine and offered them to write an assembler and disassemble based on my own ones. But this meant that I needed to convert various directives into my own ones. The challenge: I had no idea what some of those directives did! So I decide to converts so far unknown directives in comments. If they where needed by Jaak or Fred Jan, I would create code for them.Mnemonic Directive Converted into -------- ------------------------------ ---------------------------------- AORG Absolute origin .ba BES Block ending with symbol Comment BSS Block starting with symbol Comment CEND Common segment end Comment CSEG Common segment Comment DEND Data segment end Comment DORG Dummy origin Comment DSEG Data segment Comment EVEN Even boundary .ev PEND Program segment end Comment PSEG Program segment Comment RORG Relocatable origin .re IDT Program identifier Comment LIST Restart source listing Comment OPTION Output options Comment PAGE Page eject Comment TITL Page title Comment UNL Stop source listing Comment BYTE Initialize byte .by DATA Initialize word .wo EQU Define assembly-time .eq TEXT Initialize text .tx DEF External definition Comment LOAD Force load .uf REF External reference Comment SREF Secondary external reference Comment COPY Copy source file Comment END Program end .en MLIB Define macro library CommentOne can define a macro library but I have no idea how to define a macro. Anyway, it should be clear that my assembler accepts the original directives alongside the above ones as well.
The source code.
The source code is freeware, just drop me a line and it will be sent to you.You can email me here.