;******************************************************* ; ; XLT86 ; ; Translates Intel 8080 assembly language source code ; to Intel 8086 assembly language source code. ; ; 11/11/84 Frank J. Zerilli ; ; 8086 version, 11/20/84 ; VERS EQU 105 ; ;******************************************************* ; ; XLT86 processes lines with the 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. ; ; ; ; 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 ; ; 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 ; EP. ; ; 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 ; ; ADD BX,rp' ; ; Otherwise, the translation is ; ; PUSHF ; ADD BX,rp' ; POPF ; N00 EQU 0 N01 EQU 1 ; N07 EQU 7 N09 EQU 9 ; Tab every 8th col. NF8 EQU 0F8H ; Mod 8 ; LBUFLN EQU 80 ; Line buffer length OPBFLN EQU 5 ; Opcode buffer length MEMSIZ EQU 4 ; Memory available in Kb IBNUM EQU 4*MEMSIZ OBNUM EQU 4*MEMSIZ RECLEN EQU 128 ; STCKLN EQU 128 ; Stack size IBFLEN EQU IBNUM*RECLEN OBFLEN EQU OBNUM*RECLEN ; CTRLC EQU 3 EOT EQU 4 BEL EQU 7 HT EQU 9 LF EQU 0AH CR EQU 0DH ESC EQU 1BH QUOTE EQU 27H ; ; ORG 005CH ; ; DFCB1 RB 16 DFCB2 RB 16 ; FNLEN EQU 8 EOS EQU EOT ; Replacement for exclamation pt EOF EQU 1AH NFF EQU 0FFH ; Disk error return ; ; ; BDOS functions ; NABT EQU 0 NCIN EQU 1 NCOUT EQU 2 NCDAV EQU 0BH NOPEN EQU 0FH NCLOSE EQU 10H NDEL EQU 13H NRDNR EQU 14H NWRNR EQU 15H NCREAT EQU 16H NCDISK EQU 19H NDMA EQU 1AH ; ; ORG 100H ; ; JMP START ; ; ; Option flags ; PSEFLG DB 0 ; (103H) 0 to translate non- ; Standard opcodes MLTLFL DB 0FFH ; (104H) 0 to put input line with ; Exc. pt. to output on one line TCASFL DB 0 ; (105H) 0 to preserve case ; LCASFL DB 0 ; (106H) 0 for upper case if ; TCASFL not zero PSWFL DB 0 ; (107H) non-zero to preserve 8080 ; Order of PSW registers on stack INXFL DB 0 ; (108H) non-zero to preserve flags ; With INX and DCX translations DADFL DB 0 ; (109H) non-zero to preserve flags ; With DAD translation ; ; ; BDOS Functions ; BDOS: INT 224 RET ;..... ; ; ; Return to CP/M ; ABORT: MOV CL,0 MOV DL,0 INT 224 ; ; ; Help message ; HMSG1 DB CR,LF DB LF DB 'XLT86 translates Intel 8080 assembly language source',CR,LF DB 'code into Intel 8086 assembly language source code.',CR,LF DB LF DB 'It is invoked by a command of the form:',CR,LF DB LF DB ' XLT86 [d:]srcfile[.typ] [d:destfile.typ]',CR,LF DB LF DB 'The brackets denote optional parameters and the ',CR,LF DB 'default values are:',CR,LF DB LF DB ' Source file-type -- ASM',CR,LF DB ' Destination file-type -- A86',CR,LF DB ' Destination file-name -- same as source file-name',CR,LF DB ' Drive -- current drive',CR,LF DB CR,LF DB 'Press any key to continue - ',0 ; HMSG2 DB CR,LF DB LF DB 'Examples:',CR,LF DB LF DB 'XLT86 PRGM1 --translates PRGM1.ASM to PRGM1.A86',CR,LF DB 'XLT86 PRGM1 PRGM2 --translates PRGM1.ASM to PRGM2.A86',CR,LF DB 'XLT86 PRGM1.TXT PRGM2.MAC --translates PRGM1.TXT to PRGM2.MAC',CR,LF DB LF DB 'XLT86 also has the following features:',CR,LF DB LF DB 'Case will be preserved as well as possible -- if an opcode has',CR,LF DB 'a lower case character, the translated opcode will be in lower',CR,LF DB 'case.',CR,LF DB LF DB 'All asterisks at the beginning of lines will be replaced with',CR,LF DB 'semicolons.',CR,LF DB LF DB 'A dot is printed on the console for every 100 lines of input ',CR,LF DB 'processed.',CR,LF DB LF DB 0 ; ;======================================================================= ; ; ; Program begins here ; START: MOV AX,SS MOV SSBDOS,AX MOV SPBDOS,SP MOV AX,CS MOV SS,AX MOV SP,OFFSET STACK MOV AL,DFCB1+1 ; Check for a file name CMP AL,' ' ; Print help if no name JNZ BEGIN ; No help requested MOV DX,OFFSET SIGNON CALL PRTLIN MOV DX,OFFSET HMSG1 ; Print help message CALL PRTLIN MOV CL,NCIN ; Wait for any character CALL BDOS MOV DX,OFFSET HMSG2 ; Print rest of help CALL PRTLIN MOV AX,SSBDOS MOV SS,AX ; Retrieve system stack MOV SP,SPBDOS ; Pointer and pop RETF ; To PC ; BEGIN: CALL HELLO ; Signon, open in & out files ; NXTLIN: CALL GETLIN ; Get line from input file to buf CALL PROCLIN ; Process line JMP NXTLIN ;..... ; ; ;*********************************************************************** ; ; ; Print signon, open input and output files. ; HELLO: MOV DX,OFFSET SIGNON CALL PRTLIN ; HELLO0: MOV AL,'D' ; Translate DB & EQU (for MOV OPTBDB,AL ; Uniform formatting) MOV MLTSPC,HT ; For opcodes xltd to mlt stmts MOV AL,HT ; HT after opcode MOV BX,OFFSET PUTHT+1 MOV [BX],AL MOV AL,41 ; Tab comments to col 33 MOV BX,OFFSET PUTND5+1 MOV [BX],AL MOV AL,3CH ; CMP instruction MOV BX,OFFSET EXCLAM MOV [BX],AL XOR AL,AL MOV TCASFL,AL ; Don't convert case MOV LCASFL,AL ; Lower case flag MOV SEPMSG,OFFSET NEWLSP MOV AL,PSEFLG ; Translate non-standard OR AL,AL ; Opcodes ? JZ $+5 CALL NXPSD MOV DX,OFFSET DBMSG CALL PRTLIN ; CALL CHKYES ; Xlat DB & EQU ? CMP AL,ESC JNZ $+5 JMP HELLO0 CMP AL,CTRLC JNZ $+5 JMP ABORT CMP AL,'Y' JZ $+5 CALL NXDBEQ MOV AL,MLTLFL ; Force space after opcode OR AL,AL ; If MLTLFL not set JNZ $+5 JMP HELLO2 MOV DX,OFFSET SPCMSG CALL PRTLIN ; Use space after CALL CHKYES ; Opcode ? CMP AL,ESC JNZ $+5 JMP HELLO0 CMP AL,CTRLC JNZ $+5 JMP ABORT CMP AL,'Y' ; HELLO2: JNZ $+5 CALL SETSPC MOV DX,OFFSET COLMSG CALL PRTLIN ; CALL CHKYES ; Start comment CMP AL,ESC JNZ $+5 JMP HELLO0 CMP AL,CTRLC JNZ $+5 JMP ABORT CMP AL,'Y' JNZ $+5 CALL SETCOL ; In column 25 ? MOV DX,OFFSET EXCMSG CALL PRTLIN ; Ignore exclamation point CALL CHKYES ; Separator ? CMP AL,ESC JNZ $+5 JMP HELLO0 CMP AL,CTRLC JNZ $+5 JMP ABORT CMP AL,'Y' JNZ $+5 CALL SETNEX MOV DX,OFFSET MLTMSG CALL PRTLIN ; Multiple statements CALL CHKYES ; On one line ? CMP AL,ESC JNZ $+5 JMP HELLO0 CMP AL,CTRLC JNZ $+5 JMP ABORT CMP AL,'Y' JNZ $+5 CALL SETMLT MOV DX,OFFSET TRNMSG ; Convert case ? CALL PRTLIN CALL CHKYES CMP AL,ESC JNZ $+5 JMP HELLO0 CMP AL,CTRLC JNZ $+5 JMP ABORT CMP AL,'L' JNZ $+5 CALL SETLC CMP AL,'U' JNZ $+5 CALL SETUC MOV AL,N01 MOV COLNUM,AL MOV CL,NCDISK CALL BDOS INC AL MOV XCDISK,AL CALL MAKFNS CALL OPENIN CALL CREATO RET ;..... ; ; SIGNON DB '8080-to-8086 Translator version ' DB VERS/100+'0','.',(VERS MOD 100)/10+'0' DB (VERS MOD 10)+'0' DB CR,LF,0 ; ; ; Don't translate non-standard opcodes ; NXPSD: XOR AL,AL MOV OPTTDL,AL MOV OPTENT,AL MOV OPTIFC,AL RET ;..... ; ; DBMSG DB 'Translate DB & EQU ? ' DB '[Y/ret=N/esc/^C] ',0 ; NXDBEQ: XOR AL,AL MOV OPTBDB,AL RET ;..... ; ; SPCMSG DB 'Use space (default TAB) after opcode ? ' DB '[Y/ret=N/esc/^C] ',0 ; SETSPC: MOV BX,OFFSET PUTHT+1 MOV AL,' ' MOV [BX],AL MOV MLTSPC,AL RET ;..... ; ; COLMSG DB 'Start comment in column 25 (default 33) ? ' DB '[Y/ret=N/esc/^C] ',0 ; SETCOL: MOV BX,OFFSET PUTND5+1 MOV AL,33 MOV [BX],AL RET ;..... ; ; EXCMSG DB 'Ignore ! statement separator ? ' DB '[Y/ret=N/esc/^C] ',0 ; SETNEX: MOV AL,0C3H ; RET instruction MOV BX,OFFSET EXCLAM MOV [BX],AL RET ;..... ; ; MLTMSG DB 'Put opcodes converted to multiple' DB ' statements on one line ? ' DB '[Y/ret=N/esc/^C] ',0 ; SETMLT: MOV SEPMSG,OFFSET EXCLSP MOV MLTSPC,' ' RET ;..... ; ; TRNMSG DB 'Translate instructions to Upper/Lower' DB ' or preserve case ? [U/L/ret/esc/^C] ',0 ; SETLC: MOV TCASFL,AL MOV LCASFL,AL RET ;..... ; ; SETUC: MOV TCASFL,AL RET ;..... ; ; ;*********************************************************************** ; ; Gets line from input file to line buffer until CR. Filters out con- ; trol characters except for horizontal tab. Truncates lines after ; LBUFLN characters. Terminates line with CR, LF, 0. ; GETLIN: CALL PDOT ; Print activity dot CALL CHKIN CMP AL,CTRLC JNZ $+5 JMP JABORT XOR AL,AL MOV QUOTFL,AL ; Not in quote MOV CMNTFL,AL ; Not in comment MOV BX,OFFSET LBUFF ; Line buffer MOV CH,LBUFLN ; Max # of char ; GETLN1: XCHG BX,DX MOV BX,XIBUFF XCHG BX,DX MOV AL,DH CMP AL,(OFFSET IBUFF+IBFLEN)/256 JZ $+5 JMP GETLN4 MOV AL,DL CMP AL,(OFFSET IBUFF+IBFLEN) MOD 256 JZ $+5 JMP GETLN4 PUSH CX PUSH BX MOV DX,OFFSET IBUFF ; GETLN2: MOV CL,NDMA PUSH DX CALL BDOS POP DX XCHG BX,DX MOV DX,OFFSET INFCB MOV CL,NRDNR PUSH BX CALL BDOS POP BX DEC AL JZ $+5 JMP GETLN3 MOV AL,EOF MOV [BX],AL ; GETLN3: MOV DX,OFFSET RECLEN ADD BX,DX XCHG BX,DX MOV AL,DH CMP AL,(OFFSET IBUFF+IBFLEN)/256 JZ $+5 JMP GETLN2 MOV AL,DL CMP AL,(OFFSET IBUFF+IBFLEN) MOD 256 JZ $+5 JMP GETLN2 POP BX POP CX MOV DX,OFFSET IBUFF ; GETLN4: XCHG BX,DX MOV AL,[BX] XCHG BX,DX INC DX XCHG BX,DX MOV XIBUFF,BX XCHG BX,DX MOV [BX],AL CMP AL,QUOTE ; Set or reset JZ $+5 JMP GTLN41 ; QUOTFL MOV AL,QUOTFL NOT AL MOV QUOTFL,AL ; GTLN41: MOV AL,[BX] ; Translate exclam. pt. CALL EXCLAM ; Which is not in quote MOV [BX],AL ; To EOS MOV AL,TCASFL ; Translate to upper OR AL,AL ; Or lower case ? JNZ $+5 JMP GTLN46 ; NO MOV AL,QUOTFL ; If in quote, do OR AL,AL ; Nothing JZ $+5 JMP GTLN43 MOV AL,[BX] ; Otherwise, ';' sets CMP AL,';' ; CMNTFL and EOS resets JNZ $+5 JMP GTLN42 ; It CMP AL,EOS JZ $+5 JMP GTLN43 XOR AL,AL ; GTLN42: MOV CMNTFL,AL GTLN43: MOV AL,QUOTFL ; If in quote, OR AL,AL ; Do nothing JZ $+5 JMP GTLN46 MOV AL,CMNTFL ; If in comment, OR AL,AL ; Do nothing JZ $+5 JMP GTLN46 MOV AL,LCASFL ; Otherwise, OR AL,AL ; If LCASFL set MOV AL,[BX] JNZ $+5 JMP GTLN44 CALL LCASE ; Trns to lwr case JMP GTLN45 ; GTLN44: CALL UCASE ; Else trns to upr case ; GTLN45: MOV [BX],AL GTLN46: MOV AL,[BX] CMP AL,CR JNZ $+5 JMP GETLN6 CMP AL,HT ; Filters out all ctrl JNZ $+5 JMP GETLN5 ; Chars except tab CMP AL,EOF JNZ $+5 JMP GETLN7 CMP AL,EOS JNZ $+5 JMP GETLN5 CMP AL,' ' JNC $+5 JMP GETLN1 ;... ; ; GETLN5: INC BX DEC CH JZ $+5 JMP GETLN1 DEC BX INC CH JMP GETLN1 ;... ; ; GETLN6: INC BX MOV BYTE PTR [BX],LF INC BX MOV BYTE PTR [BX],N00 XCHG BX,DX MOV XIBUFF,BX XCHG BX,DX RET ;..... ; ; ; Change exclamation point to EOS in A ; EXCLAM: CMP AL,'!' JZ $+3 RET ;... ; ; MOV AL,QUOTFL OR AL,AL MOV AL,'!' JZ $+3 RET ;... ; ; MOV AL,EOS RET ;..... ; ; QUOTFL DB 0 CMNTFL DB 0 ; ; ; Exit ; GETLN7: CALL CLOSEO MOV DX,OFFSET UPSMSG CALL PRTLIN MOV DX,OFFSET ENDIFL CALL PRTLIN MOV DX,OFFSET ICLFLG CALL PRTLIN MOV DX,OFFSET LSTFLG CALL PRTLIN MOV DX,OFFSET MACFLG CALL PRTLIN MOV DX,OFFSET EOJMSG ; ; ; Print message at DE and abort ; EREXIT: PUSH DX MOV DX,OFFSET CRLFMG CALL PRTLIN POP DX CALL PRTLIN JMP ABORT ;..... ; ; JABORT: MOV DX,OFFSET JABTMG CALL PRTLIN JMP GETLN7 ;..... ; ; JABTMG DB CR,LF,'*** Job Cancelled ***',CR,LF,0 ; UPSMSG DB 0,LF,'The following operands' DB ' have been used in your ' DB 'source and have not' DB CR,LF DB 'been fully translated. You must ' DB 'complete the translation using an editor.' DB CR,LF,HT DB 'original:',HT,HT DB 'must be translated to:' DB CR,LF,0 ; ENDIFL DB 0,'IF or IFC',HT,HT,'%IF(exp)THEN(txt1)',CR,LF DB HT,'ELSE',HT,HT,HT,'ELSE(txt2)',CR,LF DB HT,'ENDIF or #ENDIF',HT,HT,'FI' DB CR,LF,0 ; ICLFLG DB 0,'ICL' DB CR,LF,0 ; LSTFLG DB 0,'LST or LIST' DB CR,LF,0 ; MACFLG DB 0,'MACRO or MAC',HT,HT,'%DEFINE(mname[(plist)])' DB CR,LF DB HT,'#macro-call',HT,HT,'%macro-call' DB CR,LF,0 ; EOJMSG DB '*** End of Job ***',CR,LF,0 ;..... ; ; ;*********************************************************************** ; ; Process line ; PROCLIN:MOV BX,OFFSET LBUFF ; PROCLN0:CALL FNDOPC JNZ PRCLN00 CALL PTCOLN ; Put out colon if JMP PUTND6 ; Colon flag set ;..... ; ; PRCLN00:MOV AL,COLNFL ; Is there a colon OR AL,AL JZ PRCLN01 MOV BX,OFFSET OPTPSD ; Don't put colon MOV CX,OPBFLN ; If opcode is CALL SCANOP ; DB, DW, DS, or EQU JZ PRCLN01 MOV AL,':' CALL PUTCHR ; PRCLN01:MOV BX,XWHITE CALL PUTSPT ; PROCLN1:MOV BX,OFFSET OPTIMM ; Imm or one byte MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DOIMM MOV BX,OFFSET OPTONE ; One byte opcodes MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DO_ONE MOV BX,OFFSET OPTREG ; Register MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DOREG MOV BX,OFFSET OPTBDB ; Db and equ MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DOSIMP MOV BX,OFFSET OPTSMP ; Simple MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DOSIMP MOV BX,OFFSET OPTROT ; Rotates MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DOROT MOV BX,OFFSET OPTDCR ; Dcr, inr MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DODCR MOV BX,OFFSET OPTWRD ; 16 bit dcx, inx MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DODCX MOV BX,OFFSET OPTTDL ; Tdl MOV CX,OPBFLN CALL SCANOP JNZ $+5 CALL DOTDL MOV BX,OFFSET OPTRCC ; Ret cond MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DORET MOV BX,OFFSET OPTCCC ; Call cond MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DOCALL MOV BX,OFFSET OPTJCC ; Jump cond MOV CX,2*OPBFLN CALL SCANOP JNZ $+5 JMP DOJMP MOV BX,OFFSET OPTMSC ; Index & misc MOV CX,2*OPBFLN+2 CALL SCANOP JNZ $+5 JMP EXEC ; PUTCOD: MOV BX,XOPCOD ; This fix prevents macro JMP PUTEND ; Names from being split ;..... ; ; PUTOPR: MOV BX,XOPRND ; PUTEND: XOR AL,AL MOV LCFLAG,AL MOV LCDFLG,AL MOV CL,N00 ; Putout w/o ; PUTND1: MOV AL,[BX] ; Change CMP AL,' ' JNZ $+5 JMP PUTND3 CMP AL,HT JNZ $+5 JMP PUTND3 CMP AL,CR JNZ $+5 JMP PUTLNC CMP AL,';' JNZ $+5 JMP PUTND4 CMP AL,EOS ; Process exclamation pt. JNZ $+5 JMP PTND21 ; Statement separator CMP AL,QUOTE JZ $+5 JMP PUTND2 DEC CL JNZ $+5 JMP PUTND2 MOV CL,N01 ; PUTND2: CALL PUTCHR INC BX JMP PUTND1 ;... ; ; PTND21: CALL SKSPHT INC BX ; Increment past exclamation point ; PTND22: MOV AL,[BX] CMP AL,';' JNZ $+5 JMP PUTND5 MOV AL,MLTLFL ; Put out as separate OR AL,AL ; Lines JNZ $+5 JMP PTND24 ; NO MOV AL,[BX] CMP AL,' ' ; Change space to HT JZ $+5 JMP PTND23 MOV BYTE PTR [BX],HT ; PTND23: CALL PCRLF JMP PROCLN0 ;... ; ; PTND24: MOV AL,TEMP ; Was last character put CMP AL,' ' ; Out a space ? JNZ $+5 JMP PTND25 CMP AL,HT ; Or a TAB ? JNZ $+5 JMP PTND25 MOV AL,' ' ; NO, put out a space CALL PUTCHR ; PTND25: MOV AL,'!' CALL PUTCHR JMP PROCLN0 ;... ; ; PUTND3: PUSH BX ; Space or Tab come here CALL SKSPHT CMP AL,CR ; This fix filters out JNZ $+5 JMP PUTLNB ; Trailing spaces or tabs POP BX CMP AL,EOS ; Fix to process excl. pt. JNZ $+5 JMP PTND21 CMP AL,';' MOV AL,[BX] ; Prevent blank being replaced JNZ $+5 JMP PUTND4 CALL PUTSPT JMP PUTND1 ; PUTND4: DEC CL ; ';' come here INC CL JZ $+5 JMP PUTND2 CALL SKSPHT ; ; ; Tab comments to proper column ; PUTND5: MOV CH,41 ; PTND51: MOV AL,COLNUM CMP AL,CH ; Colnum>=41? JC $+5 JMP PTND54 DEC AL ; No, insert AND AL,NF8 ; Tabs to ADD AL,N09 ; Start output CMP AL,CH ; At col. 33 JNZ $+5 JMP PTND54 JNC $+5 JMP PTND52 MOV AL,' ' JMP PTND53 ; PTND52: MOV AL,HT ; PTND53: CALL PUTCHR JMP PTND51 ; PTND54: MOV AL,TEMP ; Insure CMP AL,' ' ; Space JNZ $+5 JMP PUTND6 ; Before CMP AL,HT ; Semi-colon JNZ $+5 JMP PUTND6 MOV AL,' ' CALL PUTCHR ; PUTND6: MOV AL,[BX] INC BX CMP AL,EOS JNZ $+5 JMP PTND22 OR AL,AL JNZ $+3 RET ;... ; ; CALL PUTCHR JMP PUTND6 ;..... ; ; ; ; Put line at HL to output file until 0 and reset colnum to 1. ; PUTLNB: XCHG SP,BP XCHG [BP],BX XCHG SP,BP ; Filter trailing POP BX ; Blanks or tabs ; PUTLNC: JMP PUTLIN ;..... ; ; ;*********************************************************************** ; ; Process labels, find potential opcode. ; FNDOPC: MOV COLNFL,0 ; Reset colon flag MOV AL,[BX] CMP AL,' ' JNZ $+5 JMP FNDOP3 CMP AL,HT JNZ $+5 JMP FNDOP3 CMP AL,CR ; Pass blank JNZ $+3 RET ; Lines ;... ; ; CMP AL,EOS ; Excl. pt. separator JNZ $+3 RET ;... ; ; CMP AL,';' JNZ $+3 RET ;... ; ; CMP AL,'*' ; Asterisk in first column JZ $+5 JMP FNDOP1 ; Is a comment line MOV BYTE PTR [BX],';' RET ;... ; ; FNDOP1: MOV CL,N00 MOV COLNFL,':' ; Set colon flag to ; ; insure colon after label FNDOP2: MOV AL,BYTE PTR [BX] CMP AL,':' JNZ $+5 JMP FNDOP4 CMP AL,HT JNZ $+5 JMP FNDOP6 CMP AL,' ' JNZ $+5 JMP FNDOP6 CMP AL,CR JNZ $+3 RET ;... ; ; CMP AL,EOS JNZ $+3 RET ;... ; ; CMP AL,';' JNZ $+5 JMP FNDOP7 CALL PUTCHR INC BX INC CL JMP FNDOP2 ;... ; ; ; Comes here only if space or tab at beginning of line. FNDOP3: PUSH BX CALL SKSPHT ; Find first non-sp or tab CMP AL,CR JNZ $+5 JMP FNDOP9 CMP AL,EOS JNZ $+5 JMP FNDOP9 POP BX CALL PUTSPT ; Print until non-sp or ht PUSH BX CALL FINDLM ; Find ,:+-/*); CR HT or SP at HL CMP AL,':' POP BX JNZ $+5 JMP FNDOP1 JMP FNDOP7 ;... ; ; ; Colon terminating label comes here ; FNDOP4: INC BX MOV AL,[BX] CMP AL,':' JZ $+5 JMP FNDOP5 CALL PUTCHR INC BX ; FNDOP5: MOV COLNFL,':' ; Set colon flag ; ; ; HT or SP comes here ; ; See if there is an opcode field ; FNDOP6: FNDOP7: PUSH BX CALL SKSPHT MOV AL,[BX] CMP AL,CR JNZ $+5 JMP FNDOP9 ; Filter trailing SP or TAB CMP AL,EOS JNZ $+5 JMP FNDOP9 ; Excl. pt. separator CMP AL,';' JZ $+5 JMP FNDOP8 CALL PTCOLN ; Put out colon if flag set XCHG SP,BP XCHG [BP],BX XCHG SP,BP POP BX POP CX ; Clear return JMP PUTND5 ; Tab to proper column ;..... ; ; ; Have located opcode field ; FNDOP8: POP BX MOV XWHITE,BX CALL SKSPHT ; ; ; Move potential opcode to OPCBUF ; MOVOPC: MOV XOPCOD,BX MOV CH,OPBFLN MOV DX,OFFSET OPCBUF CALL MOVBDH ; Move up to B char from HL to CALL SKSPHT ; DE until ,:+-/*); CR HT SP MOV XOPRND,BX SUB AL,AL INC AL RET ;..... ; ; ; come here on CR to filter trailing SP or TAB ; FNDOP9: CALL PTCOLN ; Put out colon if flag set XCHG SP,BP XCHG [BP],BX XCHG SP,BP POP BX XOR AL,AL RET ;..... ; ; ; Put out colon if COLNFL set. ; PTCOLN: MOV AL,COLNFL OR AL,AL JZ PTCLN1 CALL PUTCHR MOV COLNFL,0 ; PTCLN1: RET ;..... ; ; COLNFL DB 0 XWHITE RW 1 ; ; ;*********************************************************************** ; ; Opcode tables ; OPTIMM DB 'ACI ADC ' DB 'ADI ADD ' DB 'ANI AND ' DB 'CPI CMP ' DB 'ORI OR ' DB 'SBI SBB ' DB 'SUI SUB ' DB 'XRI XOR ' DB 0 ; OPTONE DB 'RET RET ' DB 'CMC CMC ' DB 'HLT HLT ' DB 'STC STC ' DB 'DAA DAA ' DB 'DI CLI ' DB 'EI STI ' DB 'NOP NOP ' DB 0 ; OPTREG DB 'ADC ADC ' DB 'ADD ADD ' DB 'ANA AND ' DB 'CMP CMP ' DB 'ORA OR ' DB 'SBB SBB ' DB 'SUB SUB ' DB 'XRA XOR ' DB 0 ; OPTPSD DB 'DB ' DB 'DW ' DB 'EQU ' DB 'DS ' DB 0 ; OPTBDB DB 'DB DB ' DB 'EQU EQU ' DB 0 ; OPTSMP DB 'JMP JMP ' DB 'CALL CALL ' DB 'DS RS ' DB 'DW DW ' DB 'SET EQU ' ; OPTENT DB 'ENT ENTRY' DB 'NAM NAME ' DB 'RAM DATA ' DB 'ROG REL ' DB 0 ; OPTDCR DB 'DCR DEC ' DB 'INR INC ' DB 0 ; OPTROT DB 'RAL RCL ' DB 'RAR RCR ' DB 'RLC ROL ' DB 'RRC ROR ' DB 0 ; OPTWRD DB 'DCX DEC ' DB 'INX INC ' DB 0 ; OPTTDL DB 'REQ ' DB 'RNE ' DB 'RLT ' DB 'RGE ' DB 'CEQ ' DB 'CNE ' DB 'CLT ' DB 'CGE ' DB 'JEQ ' DB 'JNE ' DB 'JLT ' DB 'JGE ' DB 0 ; OPTRCC DB 'RC JNC ' DB 'RNC JC ' DB 'RZ JNZ ' DB 'RNZ JZ ' DB 'RP JS ' DB 'RM JNS ' DB 'RPE JPO ' DB 'RPO JPE ' DB 0 ; OPTCCC DB 'CC JNC ' DB 'CNC JC ' DB 'CZ JNZ ' DB 'CNZ JZ ' DB 'CP JS ' DB 'CM JNS ' DB 'CPE JPO ' DB 'CPO JPE ' DB 0 ; OPTJCC DB 'JC JNC ' DB 'JNC JC ' DB 'JZ JNZ ' DB 'JNZ JZ ' DB 'JP JS ' DB 'JM JNS ' DB 'JPE JPO ' DB 'JPO JPE ' DB 0 ; OPTMSC DB 'LXI MOV ' DW DOLXI DB 'POP POP ' DW DOPOP DB 'PUSH PUSH ' DW DOPSH DB 'DAD ADD ' DW DODAD DB 'LDA MOV ' DW DOLDA DB 'LDAX MOV ' DW DOLDAX DB 'LHLD MOV ' DW DOLHLD DB 'MOV MOV ' DW DOMOV DB 'MVI MOV ' DW DOMVI DB 'IN IN ' DW DOIN DB 'OUT OUT ' DW DOOUT DB 'PCHL JMP ' DW DOPCHL DB 'RST CALL ' DW DORST DB 'SHLD MOV ' DW DOSHLD DB 'SPHL MOV ' DW DOSPHL DB 'STA MOV ' DW DOSTA DB 'STAX MOV ' DW DOSTAX DB 'XCHG XCHG ' DW DOXCHG DB 'XTHL XCHG ' DW DOXTHL DB 'CMA NOT ' DW DOCMA DB 'IF IF ' DW DOIFC DB 'LIST LIST ' DW DOLST DB 'MACROMACRO' DW DOMAC ; OPTIFC DB 'IFC IF ' DW DOIFC DB 'ICL *INCL' DW DOICL DB 'LST LIST ' DW DOLST DB 'MAC MACRO' DW DOMAC DB 0 ;..... ; ; ;*********************************************************************** ; ; Scan table at HL for match to OPBFLN character string at OPCBUF. Ret ; Ret Z and BX -> entry if match. ; SCANOP: MOV AL,[BX] AND AL,AL JNZ $+5 JMP SCNOP1 PUSH CX MOV CH,OPBFLN MOV DX,OFFSET OPCBUF CALL CBDEHL ; Comp B bytes (DE)-(HL) POP CX JNZ $+3 RET ;... ; ; ADD BX,CX JMP SCANOP ;... ; ; SCNOP1: INC AL RET ;..... ; ; ; Gets routine address from HL+2*OPBFLN and jumps to routine. ; EXEC: PUSH BX MOV CX,2*OPBFLN ADD BX,CX MOV CL,[BX] INC BX MOV CH,[BX] POP BX PUSH CX ; Address on stack RET ; Go to it ;..... ; ; ; Put up to OPBFLN char at HL+OPBFLN to output file. Stop at space ; and put tab to output file. ; PUTOPHT:CALL PUTOPC ; PUTHT: MOV AL,HT JMP PUTCHR ;..... ; ; ; Put space or tab (contents of MLTSPC) to output file to separate ; opcode from operand in statements that get translated to multiple ; statements. ; PUTHTS: MOV AL,MLTSPC JMP PUTCHR ;..... ; MLTSPC DB HT ; ; PUTOPC: MOV CX,OFFSET OPBFLN ADD BX,CX ; HL -> new opcode MOV CH,CL ; PUTOP1: MOV AL,[BX] CMP AL,' ' JNZ $+3 RET ;... ; ; CMP AL,HT JNZ $+3 RET ;... ; ; MOV AL,LCFLAG OR AL,AL MOV AL,[BX] JNZ $+5 JMP PUTOP2 OR AL,20H ; PUTOP2: CALL PUTCHR INC BX DEC CH JZ $+5 JMP PUTOP1 RET ;..... ; ; ; Put string at HL to output file until 0. If (LCFLAG) set, convert to ; lower case. ; PUTOPS: MOV AL,[BX] OR AL,AL JNZ $+3 RET ;... ; ; MOV AL,LCFLAG OR AL,AL MOV AL,[BX] JNZ $+5 JMP PUTOS0 CALL LCASE ; PUTOS0: CALL PUTCHR INC BX JMP PUTOPS ;..... ; ; ; Put string at HL to output file until 0. If (LCDFLG) set, convert to ; lower case. ; PUTRND: MOV AL,[BX] OR AL,AL JNZ $+3 RET ;... ; ; MOV AL,LCDFLG OR AL,AL MOV AL,[BX] JNZ $+5 JMP PUTRN0 CALL LCASE ; PUTRN0: CALL PUTCHR INC BX JMP PUTRND ;..... ; LCDFLG DB 0 ; ; ; Find first ,:+-/*); CR HT or SP at HL, return A = (HL). ; FINDLM: PUSH CX CALL CHKDLM POP CX JNZ $+3 RET ;... ; ; INC BX JMP FINDLM ;..... ; ; ; Fill B locations at DE with spaces. Move up to B char from HL to DE ; until ,:+-/*); CR HT or SP encountered. Return Z and HL->special ; character if found. (Search B+1 loc for special char.) ; MOVBDH: MOV CL,CH MOV CH,N00 PUSH CX PUSH DX PUSH BX ; Fill BC locations CALL FILLBD ; At DE with spaces POP BX ; POP DX POP CX ; MOVBD1: PUSH CX ; Ret Z, A=(HL) CALL CHKDLM ; If (HL) is POP CX ; ,:+-/*); CR HT or SP JNZ $+3 RET ;... ; ; MOV AL,[BX] XCHG BX,DX MOV [BX],AL XCHG BX,DX INC DX INC BX DEC CX MOV AL,CH OR AL,CL JNZ $+5 JMP CHKDLM JMP MOVBD1 ;..... ; ; ; Skip spaces and tabs. Return HL -> non-space or non-tab ; SKSPHT: MOV AL,[BX] CMP AL,' ' JNZ $+5 JMP SKSPT1 CMP AL,HT JZ $+3 RET ;... ; ; SKSPT1: INC BX JMP SKSPHT ;..... ; ; ; Ret Z, A=(HL) if HL is ,:+-/*); CR HT SP or EOS ; CHKDLM: MOV AL,[BX] CMP AL,HT JZ CHKDRZ CMP AL,' ' JZ CHKDRZ CMP AL,',' JZ CHKDRZ CMP AL,';' JZ CHKDRZ CMP AL,CR JZ CHKDRZ CMP AL,':' JZ CHKDRZ CMP AL,'+' JZ CHKDRZ CMP AL,'-' JZ CHKDRZ CMP AL,'/' JZ CHKDRZ CMP AL,'*' JZ CHKDRZ CMP AL,')' JZ CHKDRZ CMP AL,EOS ; CHKDRZ: RET ;..... ; ; ; Compares B chars at DE with characters at HL. Ret Z if match. ; Preserve HL, DE, BC ; CBDEHL: PUSH BX PUSH DX PUSH CX ; CBDH1: XCHG BX,DX MOV AL,[BX] XCHG BX,DX CMP AL,'a' JNC $+5 JMP CBDH2 MOV LCFLAG,AL AND AL,05FH ; CBDH2: CMP AL,[BX] JZ $+5 JMP CBDH3 INC BX INC DX DEC CH JZ $+5 JMP CBDH1 ; CBDH3: POP CX POP DX POP BX RET ;..... ; ; LCFLAG DB 0 ; ; ; Fill BC locations starting at DE with spaces. Returns A = space, ; DE -> next free location, HL = DE - 1, BC = 0. ; FILLBD: MOV AL,' ' XCHG BX,DX MOV [BX],AL XCHG BX,DX MOV BH,DH MOV BL,DL INC DX DEC CX CALL MOVIR RET ;..... ; ; ; (DE)=(HL), INC HL, INC DE, DEC BC - repeat until BC = 0. ; MOVIR: MOV AL,[BX] XCHG BX,DX MOV [BX],AL XCHG BX,DX INC BX INC DX DEC CX MOV AL,CH OR AL,CL JZ $+5 JMP MOVIR RET ;..... ; ; ;*********************************************************************** ; ; Translation Routines ; ;******************************************************* ; ; ; Immediate i.e., XRI n -> XOR AL,n ; DOIMM: CALL PUTOPHT MOV BX,OFFSET OPALC CALL PUTOPS JMP PUTOPR ;..... ; ; OPALC DB 'AL,',0 ; ; ; One byte (implied) i.e., DI -> CLI ; DO_ONE: CALL PUTOPC JMP PUTOPR ;..... ; ; ; Simple translation i.e., DS n -> RS n ; DOSIMP: CALL PUTOPHT JMP PUTOPR ;..... ; ; ; Register instructions i.e., XRA r -> XOR AL,r' ; DOREG: CALL PUTOPHT ; Put out opcode+tab MOV BX,OFFSET OPALC CALL PUTOPS MOV BX,XOPRND CALL TRNRG JNZ DOREG1 XCHG DX,BX CALL PUTRND XCHG DX,BX ; DOREG1: JMP PUTEND ;..... ; ; ; MOV r,s -> MOV r',s' ; DOMOV: CALL PUTOPHT MOV BX,XOPRND CALL TRNRG JZ $+5 JMP PUTOPR XCHG DX,BX CALL PUTRND XCHG DX,BX MOV AL,[BX] ; Get comma INC BX ; Increment past comma CALL PUTCHR CALL TRNRG JNZ DOMOV1 XCHG DX,BX CALL PUTRND XCHG DX,BX ; DOMOV1: JMP PUTEND ;..... ; ; ; Decremebt and increment byte register ; ; DCR r -> DEC r' ; ; MVI r,n -> MOV r',n ; DODCR: DOMVI: CALL PUTOPHT MOV BX,XOPRND CALL TRNRG JNZ DOMVI2 XCHG BX,DX MOV AL,[BX] XCHG BX,DX CMP AL,'[' JNZ DOMVI1 PUSH BX MOV BX,OFFSET OPBYTP CALL PUTLIN POP BX ; DOMVI1: XCHG BX,DX CALL PUTRND XCHG BX,DX ; DOMVI2: JMP PUTEND ;..... ; ; OPBYTP DB 'BYTE PTR ',0 ; ; ; Translate 8080 byte registers to 8086 byte registers. Enter with ; BX -> to 8080 register. If match, return Z set, BX -> next, DX -> ; translation, otherwise, return NZ, BX, DX unchanged. ; TRNRG: MOV AL,[BX] CMP AL,'a' JNC $+5 JMP TRNRG2 MOV LCDFLG,AL ; TRNRG2: AND AL,5FH PUSH BX MOV BX,OFFSET RTBL MOV CH,LENGTH RTBL ; TRNRG3: CMP AL,[BX] JNZ $+5 JMP TRNRG4 INC BX DEC CH JZ $+5 JMP TRNRG3 POP BX ; HL -> R MOV AL,0FFH ; Return NZ OR AL,AL ; If no match RET ;..... ; ; TRNRG4: MOV DX,OFFSET RTBL SUB BX,DX ADD BX,BX MOV DX,OFFSET RPTBL ADD BX,DX MOV DL,[BX] INC BX MOV DH,[BX] POP BX INC BX XOR AL,AL RET ;..... ; ; RTBL DB 'ABCDEHLM' ; RTBLE: RPTBL DW ALREG DW CHREG DW CLREG DW DHREG DW DLREG DW BHREG DW BLREG DW PBX ; ALREG DB 'AL',0 CHREG DB 'CH',0 CLREG DB 'CL',0 DHREG DB 'DH',0 DLREG DB 'DL',0 BHREG DB 'BH',0 BLREG DB 'BL',0 PBX DB '[BX]',0 ; ; ; Rotates ; DOROT: CALL PUTOPHT MOV BX,OFFSET OPALC CALL PUTOPS MOV AL,'1' CALL PUTCHR JMP PUTOPR ;..... ; ; ; DAD rp -> ADD BX,rp' ; DODAD: MOV AL,DADFL OR AL,AL JZ DODAD2 PUSH BX MOV BX,OFFSET OPPSHF ; 'PUSHF' CALL PUTOPS CALL SEP ; Put out separator POP BX CALL PUTOPC CALL PUTHTS ; DODAD1: MOV BX,OFFSET OPBXC ; 'BX,' CALL PUTOPS MOV BX,XOPRND CALL TRNRP ; DX -> translated rp JZ DODAD3 JMP PUTOPR ; DODAD2: CALL PUTOPHT JMP DODAD1 ; DODAD3: XCHG BX,DX MOV AL,[BX] XCHG BX,DX CMP AL,'A' JNZ $+5 JMP PUTOPR XCHG BX,DX ; BX -> translated rp CALL PUTRND XCHG BX,DX ; BX -> next MOV AL,DADFL OR AL,AL JZ DODAD4 PUSH BX CALL SEP ; Put out separator MOV BX,OFFSET OPPOPF ; 'POPF' CALL PUTOPS POP BX ; DODAD4: JMP PUTEND ;..... ; ; OPBXC DB 'BX,',0 ; ; ; DCX or INX rp -> DEC or INC rp' ; DODCX: MOV AL,INXFL OR AL,AL JZ DODCX2 PUSH BX MOV BX,OFFSET OPPSHF ; 'PUSHF' CALL PUTOPS CALL SEP ; Put out separator POP BX CALL PUTOPC CALL PUTHTS ; DODCX1: MOV BX,XOPRND CALL TRNRP ; DX -> translated rp JZ DODCX3 JMP PUTOPR ;... ; ; DODCX2: CALL PUTOPHT JMP DODCX1 ;... ; ; DODCX3: XCHG BX,DX MOV AL,[BX] XCHG BX,DX CMP AL,'A' JNZ $+5 JMP PUTOPR XCHG BX,DX ; BX -> translated rp CALL PUTRND XCHG BX,DX ; BX -> next MOV AL,INXFL OR AL,AL JZ DODCX4 PUSH BX CALL SEP ; Put out separator MOV BX,OFFSET OPPOPF ; 'POPF' CALL PUTOPS POP BX ; DODCX4: JMP PUTEND ;..... ; ; OPPSHF DB 'PUSHF',0 OPPOPF DB 'POPF',0 ; ; ; PUSH rp -> PUSH rp' ; DOPSH: XCHG BX,DX MOV BX,XOPRND MOV AL,[BX] AND AL,5FH CMP AL,'P' XCHG BX,DX JNZ DOPSH1 XCHG BX,DX CALL TRNRP ; DE -> trans, HL -> next JZ $+5 JMP PUTCOD PUSH BX MOV BX,OFFSET OPLAHF CALL PUTRND MOV AL,PSWFL ; Preserve order of OR AL,AL ; Registers on stack ? JZ $+5 CALL XAHAL ; Yes, XCHG AH,AL CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPPUSH CALL PUTOPS CALL PUTHTS POP BX XCHG BX,DX ; BX -> translated rp CALL PUTRND XCHG BX,DX ; BX -> next MOV AL,PSWFL OR AL,AL JZ $+5 CALL XAHAL JMP PUTEND ; DOPSH1: CALL PUTOPHT ; DOPSH2: MOV BX,XOPRND CALL TRNRP ; DX -> translated rp JZ $+5 JMP PUTOPR ;..... ; ; DOPSH3: XCHG BX,DX ; BX -> translated rp CALL PUTRND XCHG BX,DX ; BX -> next JMP PUTEND ;..... ; ; OPLAHF DB 'LAHF',0 OPPUSH DB 'PUSH',0 ; XAHAL: PUSH BX CALL SEP MOV BX,OFFSET OPXCHG CALL PUTRND CALL PUTHTS MOV BX,OFFSET OPAHAL CALL PUTRND POP BX RET ;..... ; ; OPXCHG DB 'XCHG',0 OPAHAL DB 'AH,AL',0 ; ; ; POP rp -> POP rp' ; DOPOP: XCHG BX,DX ; Save BX in DX MOV BX,XOPRND MOV AL,[BX] AND AL,5FH CMP AL,'P' ; Is it PSW ? XCHG BX,DX ; Restore BX JNZ DOPSH1 CALL PUTOPC MOV AL,PSWFL OR AL,AL JZ DOPOP1 CALL PUTHTS ; Put space or tab JMP DOPOP2 ;... ; ; DOPOP1: CALL PUTHT ; DOPOP2: MOV BX,XOPRND CALL TRNRP ; DE -> trans, HL -> next JZ $+5 JMP PUTOPR XCHG BX,DX ; BX -> tranlated rp CALL PUTRND MOV AL,PSWFL OR AL,AL JZ $+5 CALL XAHAL CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPSAHF CALL PUTRND XCHG BX,DX JMP PUTEND ;..... ; ; OPSAHF DB 'SAHF',0 ; ; ; LXI rp,n -> MOV rp',OFFSET n ; DOLXI: CALL PUTOPHT MOV BX,XOPRND CALL TRNRP JZ $+5 JMP PUTOPR XCHG BX,DX MOV AL,[BX] XCHG BX,DX CMP AL,'A' JNZ $+5 JMP PUTOPR XCHG BX,DX CALL PUTRND MOV BX,OFFSET OFFATR CALL PUTLIN XCHG BX,DX ; HL -> next INC BX ; Skip comma JMP PUTEND ;..... ; ; OFFATR DB ',OFFSET ',0 ; ; ; Translate 16 bit registers. Enter with HL -> rp. Returns HL -> next ; character, DE -> translation, Z set if match, otherwise, HL unchanged, ; NZ. ; TRNRP: XOR AL,AL MOV LCDFLG,AL MOV AL,[BX] CMP AL,'a' JNC $+5 JMP TRNRP1 MOV LCDFLG,AL ; TRNRP1: AND AL,5FH CMP AL,'B' JNZ $+5 JMP TRNRPB CMP AL,'D' JNZ $+5 JMP TRNRPD CMP AL,'H' JNZ $+5 JMP TRNRPH CMP AL,'P' JNZ $+5 JMP TRNRPP CMP AL,'S' JNZ $+5 JMP TRNRPS ; TRNRP2: MOV AL,0 MOV LCDFLG,AL RET ;..... ; ; TRNRPB: MOV DX,OFFSET OPRCX ; 'CX' INC BX XOR AL,AL RET ;..... ; ; TRNRPD: MOV DX,OFFSET OPRDX ; 'DX' INC BX XOR AL,AL RET ;..... ; ; TRNRPH: MOV DX,OFFSET OPRBX ; 'BX' INC BX XOR AL,AL RET ;..... ; ; TRNRPP: INC BX MOV AL,[BX] AND AL,5FH CMP AL,'S' JZ $+5 JMP TRNRP4 INC BX MOV AL,[BX] AND AL,5FH CMP AL,'W' JZ $+5 JMP TRNRP3 MOV DX,OFFSET OPRAX ; 'AX' INC BX XOR AL,AL RET ;..... ; ; TRNRP3: DEC BX ; TRNRP4: DEC BX JMP TRNRP2 ;... ; ; TRNRPS: INC BX MOV AL,[BX] AND AL,5FH CMP AL,'P' JZ $+5 JMP TRNRP4 MOV DX,OFFSET OPRSP INC BX XOR AL,AL RET ;..... ; ; OPRAX DB 'AX',0 OPRCX DB 'CX',0 OPRDX DB 'DX',0 OPRBX DB 'BX',0 OPRSP DB 'SP',0 ; ; ; Strange opcodes ; DOTDL: MOV AL,OPCBUF+1 MOV BX,OFFSET CCZ ; 'Z ' CMP AL,'E' JNZ $+5 JMP DOTDL1 MOV BX,OFFSET CCNZ ; 'NZ' CMP AL,'N' JNZ $+5 JMP DOTDL1 MOV BX,OFFSET CCC ; 'C ' CMP AL,'L' JNZ $+5 JMP DOTDL1 MOV BX,OFFSET CCNC ; 'NC' CMP AL,'G' JNZ $+5 JMP DOTDL1 MOV BX,OFFSET CCZL CMP AL,'e' JNZ $+5 JMP DOTDL1 MOV BX,OFFSET CCNZL CMP AL,'n' JNZ $+5 JMP DOTDL1 MOV BX,OFFSET CCCL CMP AL,'l' JNZ $+5 JMP DOTDL1 MOV BX,OFFSET CCNCL ; DOTDL1: MOV AL,[BX] MOV OPCBUF+1,AL INC BX MOV AL,[BX] MOV OPCBUF+2,AL RET ;..... ; ; CCZ DB 'Z ' CCNZ DB 'NZ' CCC DB 'C ' CCNC DB 'NC' CCZL DB 'z ' CCNZL DB 'nz' CCCL DB 'c ' CCNCL DB 'nc' ; ; ; Return conditional ; DORET: CALL PUTOPC CALL PUTHT ; Could change to PUTHTS MOV BX,OFFSET REL3 CALL PUTLIN CALL SEP MOV BX,OFFSET OPRET CALL PUTOPS JMP PUTOPR ;..... ; ; REL3 DB '$+3',0 OPRET DB 'RET',0 ; ; ; Call conditional ; DOCALL: CALL PUTOPC CALL PUTHT ; Could change to PUTHTS MOV BX,OFFSET REL5 CALL PUTLIN CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPCALL CALL PUTOPS CALL PUTHTS JMP PUTOPR ; REL5 DB '$+5',0 OPCALL DB 'CALL',0 ; ; ; Jump conditional ; DOJMP: CALL PUTOPC CALL PUTHT ; Could change to PUTHTS MOV BX,OFFSET REL5 CALL PUTLIN CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPJMP CALL PUTOPS CALL PUTHTS ; Put space or tab JMP PUTOPR ;..... ; ; OPJMP DB 'JMP',0 ; ; ; IN n -> IN AL,n ; DOIN: JMP DOIMM ; ; ; LDA addr -> MOV AL,addr ; DOLDA: JMP DOIMM ; ; XCHG BX,rp' ; LDAX rp -> MOV AL,[BX] ; XCHG BX,rp' ; DOLDAX: MOV BX,XOPRND CALL TRNRP ; DE -> trans, HL -> next JZ $+5 JMP PUTCOD PUSH BX MOV BX,OFFSET OPXCHG CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPBXC CALL PUTOPS XCHG BX,DX PUSH BX CALL PUTRND CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPMOV CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPLDAX CALL PUTOPS CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPXCHG CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPBXC CALL PUTOPS POP BX ; HL -> rp' CALL PUTRND POP BX JMP PUTEND ;..... ; ; OPMOV DB 'MOV',0 OPLDAX DB 'AL,[BX]',0 ; ; ; LHLD addr -> MOV BX,addr ; DOLHLD: CALL PUTOPHT MOV BX,OFFSET OPBXC ; 'BX,' CALL PUTOPS JMP PUTOPR ;..... ; ; ; OUT n -> OUT n,AL ; DOOUT: CALL PUTOPHT CALL PUTEXP PUSH BX MOV BX,OFFSET OPCAL ; ',AL' JMP DOSTA1 ;..... ; ; ; PCHL -> JMP BX ; DOPCHL: CALL PUTOPHT MOV BX,OFFSET OPRBX ; 'BX' CALL PUTOPS JMP PUTOPR ;..... ; ; ; RST -> CALL 8* ; DORST: CALL PUTOPHT MOV BX,OFFSET OPR8M ; '8*' CALL PUTOPS JMP PUTOPR ;..... ; ; OPR8M DB '8*',0 ; ; ; SHLD addr -> MOV addr,BX ; DOSHLD: CALL PUTOPHT CALL PUTEXP PUSH BX MOV BX,OFFSET OPCBX ; ',BX' JMP DOSTA1 ;..... ; ; OPCBX DB ',BX',0 ; ; ; SPHL -> MOV SP,BX ; DOSPHL: CALL PUTOPHT MOV BX,OFFSET OPSPBX ; 'SP,BX' CALL PUTOPS JMP PUTOPR ;..... ; ; OPSPBX DB 'SP,BX',0 ; ; ; STA addr -> MOV addr,AL ; DOSTA: CALL PUTOPHT CALL PUTEXP PUSH BX MOV BX,OFFSET OPCAL ; ',AL' ; DOSTA1: CALL PUTOPS POP BX JMP PUTEND ;..... ; ; OPCAL DB ',AL',0 ; ; XCHG BX,rp' ; STAX rp -> MOV [BX],AL ; XCHG BX,rp' ; DOSTAX: MOV BX,XOPRND CALL TRNRP ; DE -> trans, HL -> next JZ $+5 JMP PUTCOD PUSH BX MOV BX,OFFSET OPXCHG CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPBXC CALL PUTOPS XCHG BX,DX PUSH BX CALL PUTRND CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPMOV CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPSTAX CALL PUTOPS CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPXCHG CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPBXC CALL PUTOPS POP BX ; HL -> rp' CALL PUTRND POP BX JMP PUTEND ;..... ; ; OPSTAX DB '[BX],AL',0 ; ; ; XCHG -> XCHG BX,DX ; DOXCHG: CALL PUTOPHT MOV BX,OFFSET OPBXDX ; 'BX,DX' CALL PUTOPS JMP PUTOPR ;..... ; ; OPBXDX DB 'BX,DX',0 ; ; XCHG SP,BP ; XTHL -> XCHG [BP],BX ; XCHG SP,BP ; DOXTHL: MOV BX,OFFSET OPXCHG CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPSPBP ; 'SP,BP' CALL PUTOPS CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPXCHG CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPXTHL CALL PUTOPS CALL SEP ; SP,EP,SP or CR, LF, HT MOV BX,OFFSET OPXCHG CALL PUTOPS CALL PUTHTS MOV BX,OFFSET OPSPBP CALL PUTOPS JMP PUTOPR ;..... ; ; OPSPBP DB 'SP,BP',0 OPXTHL DB '[BP],BX',0 ; ; ; CMA -> NOT AL ; DOCMA: CALL PUTOPHT MOV BX,OFFSET ALREG CALL PUTOPS JMP PUTOPR ;..... ; ; ; Put 'expression' to output file. 'expression' is everything between ; (xOPRND) up to the tab or spaces before a ';' or CR. ; PUTEXP: MOV BX,XOPRND ; PUTEX1: MOV AL,[BX] CMP AL,';' JNZ $+5 JMP PUTEX4 CMP AL,CR JNZ $+5 JMP PUTEX4 CMP AL,'!' JNZ $+5 JMP PUTEX3 ; PUTEX2: INC BX JMP PUTEX1 ;..... ; ; PUTEX3: DEC BX MOV AL,[BX] INC BX CMP AL,' ' JNZ $+5 JMP PUTEX4 CMP AL,HT JNZ $+5 JMP PUTEX4 JMP PUTEX2 ;..... ; ; PUTEX4: DEC BX MOV AL,[BX] CMP AL,' ' JNZ $+5 JMP PUTEX4 CMP AL,HT JNZ $+5 JMP PUTEX4 INC BX XCHG BX,DX MOV BX,XOPRND ; PUTEX5: MOV AL,DH CMP AL,BH JZ $+5 JMP PUTEX6 MOV AL,DL CMP AL,BL JNZ $+3 RET ;... ; ; PUTEX6: MOV AL,[BX] CALL PUTCHR INC BX JMP PUTEX5 ;..... ; ; ; IFC -> IF ; DOIFC: MOV AL,HT MOV ENDIFL,AL JMP DOUPS ;..... ; ; ; ICL -> *INCL ; DOICL: MOV AL,HT MOV ICLFLG,AL JMP DOUPS ;..... ; ; ; LST -> LIST ; DOLST: MOV AL,HT MOV LSTFLG,AL JMP DOUPS ;..... ; ; ; MAC -> MACRO ; DOMAC: MOV AL,HT MOV MACFLG,AL ; DOUPS: CALL PUTOPHT MOV AL,CR MOV UPSMSG,AL JMP PUTOPR ;..... ; ; ;*********************************************************************** ; ; File operations ; ;*********************************************************************** ; ; Set up input and output FCB's from DFCB ; MAKFNS: MOV BX,OFFSET DFCB1 MOV DX,OFFSET INFCB MOV CX,FNLEN+1 CALL MOVIR MOV AL,[BX] ; Typ specified ? CMP AL,' ' JNZ $+5 JMP MKFNS1 CMP AL,'?' JNZ $+5 JMP MKFNS1 MOV CX,3 CALL MOVIR ; MKFNS1: MOV BX,OFFSET DFCB1 MOV DX,OFFSET OUTFCB MOV CX,FNLEN+1 CALL MOVIR MOV AL,DFCB2 OR AL,AL ; Allows output to JNZ $+5 JMP MKFNS2 ; Different drive MOV OUTFCB,AL ; Than input ; MKFNS2: MOV AL,DFCB2+1 CMP AL,' ' JNZ $+5 JMP MKFNS3 ; Allows output MOV CX,8 ; File to have MOV DX,OFFSET OUTFCB+1 ; Different name MOV BX,OFFSET DFCB2+1 ; From input file CALL MOVIR ; MKFNS3: MOV AL,DFCB2+9 CMP AL,' ' JNZ $+5 JMP MKFNS4 MOV CX,3 MOV DX,OFFSET OUTFCB+9 MOV BX,OFFSET DFCB2+9 CALL MOVIR ; MKFNS4: MOV DX,OFFSET PRFNM1 CALL PRTLIN MOV BX,OFFSET INFCB CALL PRFNAM MOV DX,OFFSET PRFNM2 CALL PRTLIN MOV BX,OFFSET OUTFCB CALL PRFNAM MOV DX,OFFSET CRLFMG CALL PRTLIN RET ;..... ; ; ; Print Filenames ; PRFNAM: MOV AL,[BX] ; Disk number OR AL,AL JZ $+5 JMP PRFN1 MOV AL,XCDISK ; PRFN1: ADD AL,'@' CALL CONOUT MOV AL,':' CALL CONOUT INC BX MOV CH,8 CALL PRFN MOV AL,'.' CALL CONOUT MOV CH,3 ; PRFN: MOV AL,[BX] INC BX CMP AL,' ' JZ $+5 CALL CONOUT DEC CH JZ $+5 JMP PRFN RET ;..... ; ; PRFNM1 DB 'Source File: ',0 PRFNM2 DB ', Destination File: ',0 ; ; ; Open source file with ext ASM ; OPENIN: MOV DX,OFFSET INFCB MOV CL,NOPEN CALL BDOS CMP AL,NFF JNZ $+5 JMP NSFERR MOV AL,RECLEN MOV BX,OFFSET IBUFF+IBFLEN MOV XIBUFF,BX RET ;..... ; ; NSFERR: MOV DX,OFFSET NSFMSG ; 'No Source File' JMP EREXIT ;..... ; ; NSFMSG DB 'No Source File Found' DB CR,LF,BEL,0 ; INFCB DB 0,0,0,0,0,0,0,0 DB 0,'ASM',0,0,0,0 DB 0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0 DB 0 ;..... ; ; ; Create output file with ext Z80 ; CREATO: MOV DX,OFFSET OUTFCB MOV CL,NOPEN CALL BDOS CMP AL,NFF JZ $+5 JMP OFEERR ; CREAT4: MOV DX,OFFSET OUTFCB MOV CL,NCREAT CALL BDOS CMP AL,NFF JNZ $+5 JMP NDSERR MOV DX,OFFSET OUTFCB MOV CL,NOPEN CALL BDOS MOV AL,RECLEN MOV OBUFCT,AL MOV BX,OFFSET OBUFF MOV XOBUFF,BX RET ;..... ; ; NDSERR: MOV DX,OFFSET NDSMSG ; 'No directory space' JMP EREXIT ;..... ; ; NDSMSG DB 'No Directory Space' DB CR,LF,BEL,0 ; OUTFCB DB 0,0,0,0,0,0,0,0 DB 0,'A86',0,0,0,0 DB 0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0 DB 0 ;..... ; ; OFEERR: MOV DX,OFFSET OFEMSG ; 'Output file exists' CALL PRTLIN CALL CHKYES JZ $+5 JMP ABORT MOV DX,OFFSET OUTFCB MOV CL,NDEL CALL BDOS JMP CREAT4 ;..... ; ; OFEMSG DB 'Output File Already Exists' DB ' -- Delete it and Continue ? (Y/N) ' DB BEL,0 ;..... ; ; ;*********************************************************************** ; ; Put line at HL to output file until 0. ; PUTLIN: MOV AL,[BX] AND AL,AL JNZ $+3 RET ;... ; ; CALL PUTCHR INC BX JMP PUTLIN ;..... ; ; ; Put spaces or tabs at HL to output file until non-(space or tab) ; PUTSPT: MOV AL,[BX] CMP AL,' ' JNZ $+5 JMP PUTSP1 CMP AL,HT JZ $+3 RET ;... ; ; PUTSP1: CALL PUTCHR INC BX JMP PUTSPT ;..... ; ; ; Put statement separator to output file. ; SEP: MOV BX,SEPMSG JMP PUTLIN ;..... ; ; SEPMSG DW NEWLSP EXCLSP DB ' ! ',0 NEWLSP DB CR,LF,HT,0 ; ; ; Put CR, LF to output file. ; PCRLF: MOV AL,CR CALL PUTCHR MOV AL,LF ; ; ; Put character in A to output file, update column number. ; PUTCHR: PUSH BX PUSH DX PUSH CX LAHF PUSH AX MOV TEMP,AL MOV BX,XOBUFF CMP AL,EOT JNZ PCHR0 MOV AL,'!' ; PCHR0: MOV [BX],AL CMP AL,CR JZ PUTCH0 CMP AL,LF JZ PUTCH0 CMP AL,HT JNZ PUTCH1 MOV AL,COLNUM DEC AL AND AL,NF8 ADD AL,N09 JMP PUTCH2 ;... ; ; PUTCH0: MOV AL,1 JMP PUTCH2 ;... ; ; PUTCH1: MOV AL,COLNUM INC AL ; PUTCH2: MOV COLNUM,AL INC BX ; Inc obuff ptr MOV AL,OBUFCT DEC AL ; Dec obuff count JNZ PTCH21 MOV AL,RECLEN ; PTCH21: MOV OBUFCT,AL MOV AL,BH CMP AL,(OFFSET OBUFF+OBFLEN)/256 JNZ PUTCH4 MOV AL,BL CMP AL,(OFFSET OBUFF+OBFLEN) MOD 256 JNZ PUTCH4 MOV DX,OFFSET OBUFF ; PUTCH3: MOV CL,NDMA PUSH DX CALL BDOS POP DX XCHG BX,DX MOV DX,OFFSET OUTFCB CALL WRTREC ; Write record MOV DX,OFFSET RECLEN ADD BX,DX XCHG BX,DX MOV AL,DH CMP AL,(OFFSET OBUFF+OBFLEN)/256 JNZ PUTCH3 MOV AL,DL CMP AL,(OFFSET OBUFF+OBFLEN) MOD 256 JNZ PUTCH3 MOV BX,OFFSET OBUFF ; PUTCH4: MOV XOBUFF,BX POP AX SAHF POP CX POP DX POP BX RET ;..... ; ; TEMP DB 0 ; ; ; Write record. ; WRTREC: MOV CL,NWRNR PUSH BX CALL BDOS POP BX AND AL,AL JNZ $+3 RET ;... ; ; MOV DX,OFFSET OFWMSG ; 'output file write error' JMP EREXIT ;..... ; ; OFWMSG DB 'Output File Write Error' DB CR,LF,BEL,0 ; ; ; Fill rest of obuff with EOF, write record, and close file. ; CLOSEO: MOV AL,EOF CALL PUTCHR MOV AL,OBUFCT CMP AL,RECLEN JNZ CLOSEO ; CLOSE1: MOV DX,OFFSET OBUFF MOV BX,XOBUFF MOV AL,BH CMP AL,DH JNZ CLOSE3 MOV AL,BL CMP AL,DL JNZ CLOSE3 ; CLOSE2: MOV DX,OFFSET OUTFCB MOV CL,NCLOSE JMP BDOS ;..... ; ; CLOSE3: MOV CL,NDMA PUSH DX CALL BDOS POP DX XCHG BX,DX MOV DX,OFFSET OUTFCB CALL WRTREC MOV DX,RECLEN ADD BX,DX XCHG BX,DX MOV AL,BYTE PTR XOBUFF+1 CMP AL,DH JZ $+5 JMP CLOSE3 MOV AL,BYTE PTR XOBUFF CMP AL,DL JZ $+5 JMP CLOSE3 JMP CLOSE2 ;..... ; ; ; Print line at DE until 0 on console. ; PRTLIN: XCHG BX,DX MOV AL,[BX] XCHG BX,DX AND AL,AL JNZ $+3 RET ;... ; ; CALL CONOUT INC DX JMP PRTLIN ;..... ; ; ; Console Output character in A. ; CONOUT: LAHF PUSH AX PUSH CX PUSH DX PUSH BX MOV DL,AL MOV DH,N00 MOV CL,NCOUT CALL BDOS POP BX POP DX POP CX POP AX SAHF RET ;..... ; ; ; Get character from CONSOLE and return Z set if char.AND.5FH = 'Y' ; CHKYES: MOV CL,NCIN CALL BDOS LAHF PUSH AX CALL CRLF POP AX SAHF AND AL,5FH CMP AL,'Y' RET ;..... ; ; ; Return Z if no char available, otherwise, get character in A. ; CHKIN: MOV CL,NCDAV CALL BDOS OR AL,AL JNZ $+3 RET ;... ; ; MOV CL,NCIN CALL BDOS RET ;..... ; ; ; CRLF: MOV DX,OFFSET CRLFMG JMP PRTLIN ;..... ; ; CRLFMG DB CR,LF,0 ; ; ; Convert upper to lower case in A. ; LCASE: CMP AL,'A' JNC $+3 RET ;... ; ; CMP AL,'Z'+1 JC $+3 RET ;... ; ; OR AL,20H RET ;..... ; ; ; Convert lower case to upper case in A. ; UCASE: CMP AL,'a' JNC $+3 RET ;... ; ; CMP AL,'z'+1 JC $+3 RET ;... ; ; AND AL,5FH RET ;..... ; ; ; Print activity dot every 100 lines. ; PDOT: DEC LNCNT JNZ PDOT2 MOV AL,'.' CALL CONOUT MOV LNCNT,100 ; Dot every 100 lines DEC DOTCNT JNZ PDOT1 MOV AL,' ' CALL CONOUT MOV DOTCNT,10 ; Space every 10 dots ; PDOT1: DEC NLCNT JNZ PDOT2 CALL CRLF MOV NLCNT,50 ; 50 dots per line ; PDOT2: RET ;..... ; ; LNCNT DB 100 ; Dot every 100 lines DOTCNT DB 10 ; Space every 10 dots NLCNT DB 50 ; 50 dots per line ; ; ; Uninitialized storage. ; XCDISK RS 1 SSBDOS RW 1 SPBDOS RW 1 RS STCKLN STACK EQU $ COLNUM RS 1 XOPCOD RW 1 OPCBUF RS OPBFLN XOPRND RW 1 XOBUFF RW 1 OBUFCT RS 1 OBUFF RS OBFLEN LBUFF RS LBUFLN+3 XIBUFF RW 1 IBUFF RS IBFLEN ;..... ; ; END