************************************************************************ XLT86 Translates Intel 8080 assembly language source code to Intel 8086 assembly language source code. 11/11/84 Frank J. Zerilli ************************************************************************ XLT86 processes lines with DR's exclamation point statement separator correctly. It strips trailing blanks or tabs from lines. It replaces initial asterisks in lines with semicolons. It provides several options to format the output file for best appearance. This program gives the choice of converting the case of instructions to upper or lower case or of trying to preserve the case of instructions. An activity dot is printed on the console for every 100 lines of input processed. The program removes any colons terminating symbols on the same line with the pseudo-operators EQU, DB, DW, or RS and insures that all other labels are terminated with a colon. Command line: XLT86 [d:]SRCFILE[.TYP] [d:DESTFILE.TYP] All parameters in brackets are optional, and, if omitted, the default values are: Source file-type -- ASM Destination file-type -- A86 Destination file-name -- same as the source file-name Drive -- current drive Examples: XLT86 PRGM1 -- translates PRGM1.ASM to PRGM1.A86 XLT86 PRGM1 PRGM2 -- translates PRGM1.ASM to PRGM2.A86 XLT86 PRGM1.TXT PRGM2.MAC -- translates PRGM1.TXT to PRGM2.MAC FLAG LOCATIONS: 103H -- Change to non-zero value to suppress translation of several non-standard opcodes: REQ, RNE, RLT, RGE, CEQ, CNE, CLT, CGE JEQ, JNE, JLT, JGE, ENT, NAM, RAM, ROG, IFC, ICL, LST, MAC 104H -- If non-zero (default) XLT86 converts lines with multiple statements separated by DR's EP separator into separate lines. Change to zero for output on a single line with the translated statements separated by exclamation point (!). 107H -- If zero (default) XLT86 translates PUSH PSW POP PSW to LAHF POP AX PUSH AX SAHF Otherwise, the translation is LAHF POP AX XCHG AH,AL XCHG AH,AL PUSH AX SAHF XCHG AH,AL 108H -- If zero (default) XLT86 translates INX rp DCX rp to INC rp' DEC rp' Otherwise, the translation is PUSHF PUSHF INC rp' DEC rp' POPF POPF 109H -- If zero (default) XLT86 translates DAD rp to ------------- | rp | rp' | ADD BX,rp' |-----|-----| | B | CX | Otherwise, the translation is | D | DX | | H | BX | PUSHF | SP | SP | ADD BX,rp' ------------- POPF The distributed version of XLT86 uses 4K of buffer space, 2K for the input buffer and 2K for the output buffer. This can be changed by changing the equate MEMSIZ (currently set to 4) to the total buffer space desired (in Kb) and reassembling the program. However, increasing the buffer space beyond 4K will not significantly increase the speed of translation. For example, a 36K file was translated in 44 seconds (input and output files on the same double density 8" floppy) with MEMSIZ = 4 and in 42 seconds with MEMSIZ = 32. Disk activity may be less with larger buffers, however. This program is based on similar programs for 8080-Z80 conversion (XLATE2, XLT80, XLTZ80). It is a simple-minded program. While a simple minded program is ok for translation between 8080 and Z80 mnemonics, it is not as good for 8080 to 8086 conversion so that you will have to do a fair amount of editing of the converted file to get it to work properly. Following is a list of items to check for (it's by no means complete) in your post-conversion editing. Some of the following items are specific to CPM-86 and Digital Research's ASM86 although many will also apply to Intel's ASM86 assembler. 1) BDOS FUNCTION CALLS Replace call to location 0005 (CALL BDOS) with INT 224: for example, replace BDOS EQU 5 with BDOS: INT 224 RET Alternatively, replace all CALL BDOS or CALL 5 with INT 224. 2) RETURN TO CCP Replace jumps to location 0000 (abort) with call to BDOS function 0: for example, replace ABORT EQU 0 with ABORT: MOV CL,0 MOV DL,0 CALL BDOS An alternative is to restore the CCP stack pointer (you have to have saved it, of course) and do a RETF. *** Important Note: if the program uses a local stack instead of the CCP stack then be sure to set SS (stack segment) register to the same value as the CS (code segment) register. For example: START: MOV AX,SS MOV CCPSS,AX ; save CCP SS register MOV CCPSP,SP ; save CCP stack pointer MOV SP,OFFSET STACK ; set local stack MOV AX,CS MOV SS,AX ; set SS register to CS register . . . ABORT: MOV AX,CCPSS MOV SS,AX ; restore CCP SS register MOV SP,CCPSP ; restore CCP stack pointer RETF ; return to CCP CCPSS RW 1 CCPSP RW 1 RW STACKLENGTH STACK EQU $ 3) ALLOWED CHARACTERS IN SYMBOLS Change any '$' in symbols to '@' or '_'. 4) PAGE 0 EQUATES Replace equates which define page 0 addresses with data defining pseudo-ops: for example, replace DFCB1 EQU 005CH with ORG 005CH DFCB1 RS 16 Alternatively, add '.' to references to page 0 equates. For example, change any reference like MOV AL,DFCB1 to MOV AL,.DFCB1 Reason: MOV AL,DFCB1 is probably the translation of LDA DFCB1 (it could also have come from MVI A,DFCB1 but this would only be due to the weirdness of the programmer). The period operator converts a symbol of type number (DFCB1 got the type of number from the EQU to 005CH) into a variable. 5) LABELS WHICH SHOULD HAVE THE WORD TYPE ATTRIBUTE Change statements like WORDLABEL RS 2 to WORDLABEL RW 1 At the same time, change statements like MOV AL,WORDLABEL+1 to MOV AL,BYTE PTR WORDLABEL+1 Reason: the assembler is very fussy about typing of operands 6) LABELS WHICH ARE ADDRESSES OF EXECUTABLE INSTRUCTIONS Change statements like MOV AL,CODELABEL to MOV AL,BYTE PTR CODELABEL (where CODELABEL is the symbol for a code segment address) 7) CONVERTING ADDRESSES TO NUMBERS Change statements like CMP AL,(BUFFER_ADDRESS + BUFFER_LENGTH)/256 to CMP AL,(OFFSET BUFFER_ADDRESS + BUFFER_LENGTH)/256 8) CONVERTING ADDRESSES TO NUMBERS (continued) Change statements like MOV CL,TABLE_END - TABLE_START to MOV CL,OFFSET TABLE_END - OFFSET TABLE_START 9) OPCODES WHICH AFFECT FLAGS Watch out for this: unlike the 8080, incrementing and decrementing 16 bit registers in the 8086 will affect the flags. So if you have some 8080 code like RETZER: MVI B,1 LXI H,0 DCR B INX H RET which would return with the zero flag set, it will be translated to RETZER: MOV CH,1 MOV BX,0 DEC CH INC BX RET which will return with the zero flag reset ! Therefore, the code must be changed to RETZER: MOV CH,1 MOV BX,0 INC BX DEC CH RET which will return the flag as originally intended. XLT86 has a option (set location offset 108H non-zero) to translate INX rp or DCX rp (rp stands for register pair B, D, H, or SP) to the sequence PUSHF INC or DEC rp' POPF There is a similar problem with DAD rp which affects only the carry flag in the 8080. Its translation is ADD BX,rp' which affects sign, zero, half carry, parity, and overflow as well as the carry flag. Setting location offset 109H in XLT86 to non-zero will PUSHF and POPF as for INX and DCX but in this case there is still a problem if the result of the operation on the carry flag must be preserved. 10) PUSH or POP PSW In the 8080, the A registers is the high byte of the word pushed onto the stack. The translation is PUSH AX in which the register corresponding to A is AL which is the low byte of the word pushed onto the stack. This is would not be a problem unless the program tries to pick the register directly from the stack. Setting the location offset 107H in XLT86 to non-zero will cause the translated program to include an XCHG AH,AL before and after pushing to (and after popping from) the stack.