TITLE DEBASM ; Code for the ASSEMble command in the debugger .xlist .xcref INCLUDE DEBEQU.ASM INCLUDE DOSSYM.ASM .cref .list CODE SEGMENT PUBLIC BYTE 'CODE' CODE ENDS CONST SEGMENT PUBLIC BYTE EXTRN DBMN:BYTE,CSSAVE:WORD,REG8:BYTE,REG16:BYTE,SIZ8:BYTE EXTRN SYNERR:BYTE,OPTAB:BYTE,MAXOP:ABS CONST ENDS DATA SEGMENT PUBLIC BYTE EXTRN HINUM:WORD,LOWNUM:WORD,ASSEM_CNT:BYTE EXTRN ASSEM1:BYTE,ASSEM2:BYTE,ASSEM3:BYTE,ASSEM4:BYTE,ASSEM5:BYTE EXTRN ASSEM6:BYTE,OPBUF:BYTE,OPCODE:WORD,REGMEM:BYTE,INDEX:WORD EXTRN ASMADD:BYTE,ASMSP:WORD,MOVFLG:BYTE,SEGFLG:BYTE,TSTFLG:BYTE EXTRN NUMFLG:BYTE,DIRFLG:BYTE,BYTEBUF:BYTE,F8087:BYTE,DIFLG:BYTE EXTRN SIFLG:BYTE,BXFLG:BYTE,BPFLG:BYTE,NEGFLG:BYTE,MEMFLG:BYTE EXTRN REGFLG:BYTE,AWORD:BYTE,MIDFLD:BYTE,MODE:BYTE DATA ENDS DG GROUP CODE,CONST,DATA CODE SEGMENT PUBLIC BYTE 'CODE' ASSUME CS:DG,DS:DG,ES:DG,SS:DG PUBLIC ASSEM PUBLIC DB_OPER,DW_OPER,ASSEMLOOP,GROUP2,AA_OPER,DCINC_OPER PUBLIC GROUP1,ESC_OPER,FGROUPP,FGROUPX,FDE_OPER,FGROUPZ PUBLIC FD9_OPER,FGROUP,FDB_OPER,FGROUPB,FGROUP3,FGROUP3W PUBLIC FGROUPDS,INT_OPER,IN_OPER,DISP8_OPER,JMP_OPER,NO_OPER PUBLIC OUT_OPER,L_OPER,MOV_OPER,POP_OPER,PUSH_OPER,ROTOP PUBLIC TST_OPER,EX_OPER,GET_DATA16,CALL_OPER EXTRN INBUF:NEAR,SCANB:NEAR,SCANP:NEAR,GETHX:NEAR,GET_ADDRESS:NEAR EXTRN DEFAULT:NEAR,OUTDI:NEAR,BLANK:NEAR,PRINTMES:NEAR,TAB:NEAR ; ; Line by line assembler ; ASSEM: MOV BP,[CSSAVE] ; Default code segment MOV DI,OFFSET DG:ASMADD ; Default address CALL DEFAULT MOV WORD PTR [ASMADD],DX ; Displacement of disassembly MOV WORD PTR [ASMADD+2],AX ; Segment MOV [ASMSP],SP ; Save sp in case of error ASSEMLOOP: MOV SP,[ASMSP] ; Restore sp in case of error LES DI,DWORD PTR ASMADD ; GET PC CALL OUTDI ; OUTPUT ADDRESS CALL BLANK ; SKIP A SPACE PUSH CS POP ES CALL INBUF ; GET A BUFFER CALL SCANB JNZ OPLOOK RET ; IF EMPTY JUST RETURN ; ; At this point ds:si points to the opcode mnemonic... ; OPLOOK: XOR CX,CX ; OP-CODE COUNT = 0 MOV DI,OFFSET DG:DBMN OPSCAN: XOR BX,BX OPLOOP: MOV AL,[DI+BX] AND AL,7FH CMP AL,[SI+BX] JZ OPMATCH INC CX ; INCREMENT OP-CODE COUNT CMP CX,MAXOP ; CHECK FOR END OF LIST JB OP1 JMP ASMERR OP1: INC DI ; SCAN FOR NEXT OP-CODE... TEST BYTE PTR [DI-1],80H JZ OP1 JMP OPSCAN OPMATCH:INC BX ; COMPARE NEXT CHAR TEST BYTE PTR [DI+BX-1],80H ; ARE WE DONE? JZ OPLOOP ; ..IF NOT KEEP COMPARING XCHG BX,CX MOV AX,BX SHL AX,1 ADD AX,BX ADD AX,OFFSET DG:OPTAB MOV BX,AX ; ; CX = COUNT OF CHARS IN OPCODE ; BX = POINTER INTO OPCODE TABLE ; XOR AX,AX MOV BYTE PTR [AWORD],AL MOV WORD PTR [MOVFLG],AX ; MOVFLG + TSTFLG MOV BYTE PTR [SEGFLG],AL ; ZERO SEGMENT REGISTER FLAG MOV AH,00001010B ; SET UP FOR AA_OPER MOV AL,BYTE PTR [BX] MOV WORD PTR [ASSEM1],AX MOV BYTE PTR [ASSEM_CNT],1 ADD SI,CX ; SI POINTS TO OPERAND JMP WORD PTR [BX+1] ; ; 8087 INSTRUCTIONS WITH NO OPERANDS ; FDE_OPER: MOV AH,0DEH JMP SHORT FDX_OPER FDB_OPER: MOV AH,0DBH JMP SHORT FDX_OPER FD9_OPER: MOV AH,0D9H FDX_OPER: XCHG AL,AH MOV WORD PTR [ASSEM1],AX ; ; aad and aam instrucions ; AA_OPER:INC BYTE PTR [ASSEM_CNT] ; ; instructions with no operands ; NO_OPER: CALL STUFF_BYTES CALL SCANP PUSH CS POP ES JNZ OPLOOK JMP ASSEMLOOP ; ; push instruction ; PUSH_OPER: MOV AH,11111111B JMP SHORT POP1 ; ; pop instruction ; POP_OPER: MOV AH,10001111B POP1: MOV [ASSEM1],AH MOV [MIDFLD],AL INC BYTE PTR [MOVFLG] ; ALLOW SEGMENT REGISTERS MOV BYTE PTR [AWORD],2 ; MUST BE 16 BITS CALL GETREGMEM CALL BUILDIT MOV AL,[DI+2] CMP AL,11000000B JB DATRET MOV BYTE PTR [DI],1 CMP BYTE PTR [MOVFLG],2 JNZ POP2 AND AL,00011000B OR AL,00000110B CMP BYTE PTR [MIDFLD],0 JNZ POP3 OR AL,00000001B JMP SHORT POP3 POP2: AND AL,111B OR AL,01010000B CMP BYTE PTR [MIDFLD],0 JNZ POP3 OR AL,01011000B POP3: MOV BYTE PTR [DI+1],AL JMP ASSEM_EXIT ; ; ret and retf instructions ; GET_DATA16: CALL SCANB MOV CX,4 CALL GETHX JC DATRET DEC BYTE PTR [ASSEM1] ; CHANGE OP-CODE ADD BYTE PTR [ASSEM_CNT],2 ; UPDATE LENGTH MOV WORD PTR [ASSEM2],DX ; SAVE OFFSET DATRET: JMP ASSEM_EXIT ; ; int instruction ; INT_OPER: CALL SCANB MOV CX,2 CALL GETHX JC ERRV1 MOV AL,DL CMP AL,3 JZ DATRET INC BYTE PTR [ASSEM1] JMP DISPX ; ; in instruction ; IN_OPER: CALL SCANB LODSW CMP AX,"A"+4C00H ; "AL" JZ IN_1 CMP AX,"A"+5800H ; "AX" JZ IN_0 ERRV1: JMP ASMERR IN_0: INC BYTE PTR [ASSEM1] IN_1: CALL SCANP CMP WORD PTR [SI],"D"+5800H ; "DX" JZ DATRET MOV CX,2 CALL GETHX JC ERRV1 AND BYTE PTR [ASSEM1],11110111B MOV AL,DL JMP DISPX ; ; out instruction ; OUT_OPER: CALL SCANB CMP WORD PTR [SI],"D"+5800H ; "DX" JNZ OUT_0 INC SI INC SI JMP SHORT OUT_1 OUT_0: AND BYTE PTR [ASSEM1],11110111B MOV CX,2 CALL GETHX JC ERRV1 INC BYTE PTR [ASSEM_CNT] MOV BYTE PTR [ASSEM2],DL OUT_1: CALL SCANP LODSW CMP AX,"A"+4C00H ; "AL" JZ DATRET CMP AX,"A"+5800H ; "AX" JNZ ERRV1 INC BYTE PTR [ASSEM1] JMP DATRET ; ; jump instruction ; JMP_OPER: INC BYTE PTR [TSTFLG] ; ; call instruction ; CALL_OPER: MOV BYTE PTR [ASSEM1],11111111B MOV BYTE PTR [MIDFLD],AL CALL GETREGMEM CALL BUILD3 CMP BYTE PTR [MEMFLG],0 JNZ CALLJ1 CMP BYTE PTR [REGMEM],-1 JZ CALLJ2 ; ; INDIRECT JUMPS OR CALLS ; CALLJ1: CMP BYTE PTR [AWORD],1 ERRZ4: JZ ERRV1 CMP BYTE PTR [AWORD],4 JNZ ASMEX4 OR BYTE PTR [DI+2],1000B JMP SHORT ASMEX4 ; ; DIRECT JUMPS OR CALLS ; CALLJ2: MOV AX,[LOWNUM] MOV DX,[HINUM] MOV BL,[AWORD] CMP BYTE PTR [NUMFLG],0 JZ ERRZ4 ; BL = NUMBER OF BYTES IN JUMP ; DX = OFFSET ; AX = SEGMENT CALLJ3: MOV BYTE PTR [DI],5 MOV [DI+2],AX MOV [DI+4],DX MOV AL,10011010B ; SET UP INTER SEGMENT CALL CMP BYTE PTR [TSTFLG],0 JZ CALLJ5 MOV AL,11101010B ; FIX UP FOR JUMP CALLJ5: MOV BYTE PTR [DI+1],AL CMP BL,4 ; FAR SPECIFIED? JZ ASMEX4 OR BL,BL JNZ CALLJ6 CMP DX,WORD PTR [ASMADD+2] ; DIFFERENT SEGMENT? JNZ ASMEX4 CALLJ6: MOV BYTE PTR [DI],3 MOV AL,11101000B ; SET UP FOR INTRASEGMENT OR AL,[TSTFLG] MOV BYTE PTR [DI+1],AL MOV AX,[LOWNUM] SUB AX,WORD PTR [ASMADD] SUB AX,3 MOV [DI+2],AX CMP BYTE PTR [TSTFLG],0 JZ ASMEX4 CMP BL,2 JZ ASMEX4 INC AX MOV CX,AX CBW CMP AX,CX JNZ ASMEX3 MOV BYTE PTR [DI+1],11101011B MOV [DI+2],AX DEC BYTE PTR [DI] ASMEX4: JMP ASSEM_EXIT ; ; conditional jumps and loop instructions ; DISP8_OPER: MOV BP,WORD PTR [ASMADD+2] ; GET DEFAULT DISPLACEMENT CALL GET_ADDRESS SUB DX,WORD PTR [ASMADD] DEC DX DEC DX CALL CHKSIZ CMP CL,1 JNZ ERRV2 DISPX: INC [ASSEM_CNT] MOV BYTE PTR [ASSEM2],AL ASMEX3: JMP ASSEM_EXIT ; ; lds, les, and lea instructions ; L_OPER: CALL SCANB LODSW MOV CX,8 MOV DI,OFFSET DG:REG16 CALL CHKREG JZ ERRV2 ; CX = 0 MEANS NO REGISTER SHL AL,1 SHL AL,1 SHL AL,1 MOV BYTE PTR [MIDFLD],AL CALL SCANP CALL GETREGMEM CMP BYTE PTR [AWORD],0 JNZ ERRV2 CALL BUILD2 JMP SHORT ASEXV ; ; dec and inc instructions ; DCINC_OPER: MOV BYTE PTR [ASSEM1],11111110B MOV BYTE PTR [MIDFLD],AL CALL GETREGMEM CALL BUILDIT TEST BYTE PTR [DI+1],1 JZ ASEXV MOV AL,[DI+2] CMP AL,11000000B JB ASEXV AND AL,1111B OR AL,01000000B MOV [DI+1],AL DEC BYTE PTR [DI] ASEXV: JMP ASSEM_EXIT ERRV2: JMP ASMERR ; ; esc instruction ; ESC_OPER: INC BYTE PTR [AWORD] CALL SCANB MOV CX,2 CALL GETHX CMP DX,64 JAE ERRV2 CALL SCANP MOV AX,DX MOV CL,3 SHR DX,CL OR [ASSEM1],DL AND AL,111B SHL AL,CL JMP GROUPE ; ; 8087 arithmetic instuctions ; ; ; OPERANDS THAT ALLOW THE REVERSE BIT ; FGROUPDS: CALL SETMID CALL GETREGMEM2 CALL BUILD3 CMP BYTE PTR [MODE],11000000B JNZ FGROUP1 MOV AL,[DIRFLG] OR AL,AL JZ FEXIT OR [DI+1],AL ; IF D=1... XOR BYTE PTR [DI+2],00001000B ; ...REVERSE THE SENSE OF R JMP SHORT FEXIT ; ; Here when instruction could have memory or register operand ; FGROUPX: CALL SETMID ; THIS ENTRY POINT FOR 1 MEM OPER MOV BYTE PTR [DIRFLG],0 JMP SHORT FGRP2 FGROUP: CALL SETMID FGRP2: CALL GETREGMEM2 CALL BUILD3 CMP BYTE PTR [MODE],11000000B JNZ FGROUP1 MOV AL,[DIRFLG] OR [DI+1],AL JMP SHORT FEXIT FGROUP1:CALL SETMF FEXIT: JMP ASSEM_EXIT ; ; These 8087 instructions require a memory operand ; FGROUPB: MOV AH,5 ; MUST BE TBYTE JMP SHORT FGROUP3E FGROUP3W: MOV AH,2 ; MUST BE WORD JMP SHORT FGROUP3E FGROUP3: MOV AH,-1 ; SIZE CANNOT BE SPECIFIED FGROUP3E: MOV [AWORD],AH CALL SETMID CALL GETREGMEM CMP BYTE PTR [MODE],11000000B JZ FGRPERR FGRP: CALL BUILD3 JMP FEXIT ; ; These 8087 instructions require a register operand ; FGROUPP: ; 8087 POP OPERANDS MOV BYTE PTR [AWORD],-1 CALL SETMID CALL GETREGMEM2 CMP BYTE PTR [DIRFLG],0 JNZ FGRP FGRPERR:JMP ASMERR FGROUPZ: ; ENTRY POINT WHERE ARG MUST BE MEM CALL SETMID MOV BYTE PTR [DIRFLG],0 CALL GETREGMEM CMP BYTE PTR [MODE],11000000B JZ FGRPERR CALL BUILD3 CALL SETMF JMP FEXIT ; ; not, neg, mul, imul, div, and idiv instructions ; GROUP1: MOV [ASSEM1],11110110B GROUPE: MOV BYTE PTR [MIDFLD],AL CALL GETREGMEM CALL BUILDIT JMP FEXIT ; ; shift and rotate instructions ; ROTOP: MOV [ASSEM1],11010000B MOV BYTE PTR [MIDFLD],AL CALL GETREGMEM CALL BUILDIT CALL SCANP CMP BYTE PTR [SI],"1" JZ ASMEXV1 CMP WORD PTR [SI],"LC" ; CL JZ ROTOP1 ROTERR: JMP ASMERR ROTOP1: OR BYTE PTR [ASSEM1],10B ASMEXV1:JMP ASSEM_EXIT ; ; xchg instruction ; EX_OPER: INC BYTE PTR [TSTFLG] ; ; test instruction ; TST_OPER: INC BYTE PTR [TSTFLG] JMP SHORT MOVOP ; ; mov instruction ; MOV_OPER: INC BYTE PTR [MOVFLG] MOVOP: XOR AX,AX JMP SHORT GROUPM ; ; add, adc, sub, sbb, cmp, and, or, xor instructions ; GROUP2: MOV BYTE PTR [ASSEM1],10000000B GROUPM: MOV BYTE PTR [MIDFLD],AL PUSH AX CALL GETREGMEM CALL BUILD2 CALL SCANP ; POINT TO NEXT OPERAND MOV AL,BYTE PTR [ASSEM_CNT] PUSH AX CALL GETREGMEM POP AX MOV BYTE PTR [DI],AL POP AX MOV BL,BYTE PTR [AWORD] OR BL,BL JZ ERRV5 DEC BL AND BL,1 OR BYTE PTR [DI+1],BL CMP BYTE PTR [MEMFLG],0 JNZ G21V CMP BYTE PTR [NUMFLG],0 ; TEST FOR IMMEDIATE DATA JZ G21V CMP BYTE PTR [SEGFLG],0 JNZ ERRV5 CMP BYTE PTR [TSTFLG],2 ; XCHG? JNZ IMMED1 ERRV5: JMP ASMERR G21V: JMP GRP21 ; ; SECOND OPERAND WAS IMMEDIATE ; IMMED1: MOV AL,BYTE PTR [DI+2] CMP BYTE PTR [MOVFLG],0 JZ NOTMOV1 AND AL,11000000B CMP AL,11000000B JNZ GRP23 ; not to a register ; MOVE IMMEDIATE TO REGISTER MOV AL,BYTE PTR [DI+1] AND AL,1 ; SET SIZE PUSHF SHL AL,1 SHL AL,1 SHL AL,1 OR AL,BYTE PTR [DI+2] ; SET REGISTER AND AL,00001111B OR AL,10110000B MOV BYTE PTR [DI+1],AL MOV AX,WORD PTR [LOWNUM] MOV WORD PTR [DI+2],AX POPF JZ EXVEC INC BYTE PTR [DI] EXVEC: JMP GRPEX NOTMOV1:AND AL,11000111B CMP AL,11000000B JZ IMMACC ; IMMEDIATE TO ACC CMP BYTE PTR [TSTFLG],0 JNZ GRP23 CMP BYTE PTR [MIDFLD],1*8 ; OR? JZ GRP23 CMP BYTE PTR [MIDFLD],4*8 ; AND? JZ GRP23 CMP BYTE PTR [MIDFLD],6*8 ; XOR? JZ GRP23 TEST BYTE PTR [DI+1],1 ; TEST IF BYTE OPCODE JZ GRP23 MOV AX,[LOWNUM] MOV BX,AX CBW CMP AX,BX JNZ GRP23 ; SMALL ENOUGH? MOV BL,[DI] DEC BYTE PTR [DI] OR BYTE PTR [DI+1],10B JMP SHORT GRP23X IMMACC: MOV AL,BYTE PTR [DI+1] AND AL,1 CMP BYTE PTR [TSTFLG],0 JZ NOTTST OR AL,10101000B JMP SHORT TEST1 NOTTST: OR AL,BYTE PTR [MIDFLD] OR AL,100B TEST1: MOV BYTE PTR [DI+1],AL DEC BYTE PTR [DI] GRP23: MOV BL,BYTE PTR [DI] GRP23X: XOR BH,BH ADD BX,DI INC BX MOV AX,WORD PTR [LOWNUM] MOV WORD PTR [BX],AX INC BYTE PTR [DI] TEST BYTE PTR [DI+1],1 JZ GRPEX1 INC BYTE PTR [DI] GRPEX1: JMP GRPEX ; ; SECOND OPERAND WAS MEMORY OR REGISTER ; GRP21: CMP BYTE PTR [SEGFLG],0 JZ GRP28 ; FIRST OPERAND WAS A SEGMENT REG MOV AL,BYTE PTR [REGMEM] TEST AL,10000B JZ NOTSEG1 ERRV3: JMP ASMERR NOTSEG1:AND AL,111B OR BYTE PTR [DI+2],AL AND BYTE PTR [DI+1],11111110B CMP BYTE PTR [MEMFLG],0 JNZ G22V JMP GRPEX GRP28: AND BYTE PTR [DI+2],11000111B MOV AL,BYTE PTR [DI+1] ; GET FIRST OPCODE AND AL,1B CMP BYTE PTR [MOVFLG],0 JZ NOTMOV2 OR AL,10001000B JMP SHORT MOV1 NOTMOV2:CMP BYTE PTR [TSTFLG],0 JZ NOTTST2 OR AL,10000100B CMP BYTE PTR [TSTFLG],2 JNZ NOTTST2 OR AL,10B NOTTST2:OR AL,BYTE PTR [MIDFLD] ; MIDFLD IS ZERO FOR TST MOV1: MOV BYTE PTR [DI+1],AL CMP BYTE PTR [MEMFLG],0 G22V: JNZ GRP22 ; ; SECOND OPERAND WAS A REGISTER ; MOV AL,BYTE PTR [REGMEM] TEST AL,10000B ; SEGMENT REGISTER? JZ NOTSEG CMP BYTE PTR [MOVFLG],0 JZ ERRV3 MOV BYTE PTR [DI+1],10001100B NOTSEG: AND AL,111B SHL AL,1 SHL AL,1 SHL AL,1 OR BYTE PTR [DI+2],AL ; ; SPECIAL FORM OF THE EXCHANGE COMMAND ; CMP BYTE PTR [TSTFLG],2 JNZ GRPEX TEST BYTE PTR [DI+1],1 JZ GRPEX PUSH AX MOV AL,BYTE PTR [DI+2] AND AL,11000000B CMP AL,11000000B ; MUST BE REGISTER TO REGISTER POP AX JB GRPEX OR AL,AL JZ SPECX MOV AL,[DI+2] AND AL,00000111B JNZ GRPEX MOV CL,3 SHR BYTE PTR [DI+2],CL SPECX: MOV AL,[DI+2] AND AL,00000111B OR AL,10010000B MOV BYTE PTR [DI+1],AL DEC BYTE PTR [DI] JMP SHORT GRPEX ; ; SECOND OPERAND WAS A MEMORY REFERENCE ; GRP22: CMP BYTE PTR [TSTFLG],0 JNZ TST2 OR BYTE PTR [DI+1],10B TST2: MOV AL,BYTE PTR [DI+2] CMP AL,11000000B ; MUST BE A REGISTER JB ASMERR CMP BYTE PTR [SEGFLG],0 JZ GRP223 AND AL,00011000B JMP SHORT GRP222 GRP223: AND AL,111B SHL AL,1 SHL AL,1 SHL AL,1 GRP222: OR AL,BYTE PTR [MODE] OR AL,BYTE PTR [REGMEM] MOV BYTE PTR [DI+2],AL MOV AX,WORD PTR [LOWNUM] MOV WORD PTR [DI+3],AX GRPSIZ: MOV BYTE PTR [DI],2 MOV AL,BYTE PTR [DI+2] AND AL,11000111B CMP AL,00000110B JZ GRP24 AND AL,11000000B CMP AL,01000000B JZ GRP25 CMP AL,10000000B JNZ GRPEX GRP24: INC BYTE PTR [DI] GRP25: INC BYTE PTR [DI] GRPEX: CMP BYTE PTR [MOVFLG],0 JZ ASSEM_EXIT ; ; TEST FOR SPECIAL FORM OF MOV AX,[MEM] OR MOV [MEM],AX ; MOV AL,[DI+1] ; GET OP-CODE AND AL,11111100B CMP AL,10001000B JNZ ASSEM_EXIT CMP BYTE PTR [DI+2],00000110B ; MEM TO AX OR AX TO MEM JNZ ASSEM_EXIT MOV AL,BYTE PTR [DI+1] AND AL,11B XOR AL,10B OR AL,10100000B MOV BYTE PTR [DI+1],AL DEC BYTE PTR [DI] MOV AX,[DI+3] MOV WORD PTR [DI+2],AX ASSEM_EXIT: CALL STUFF_BYTES JMP ASSEMLOOP ; Assem error. SI points to character in the input buffer ; which caused error. By subtracting from start of buffer, ; we will know how far to tab over to appear directly below ; it on the terminal. Then print "^ Error". ASMERR: SUB SI,OFFSET DG:(BYTEBUF-10) ; How many char processed so far? MOV CX,SI ; Parameter for TAB in CX CALL TAB ; Directly below bad char MOV SI,OFFSET DG:SYNERR ; Error message CALL PRINTMES JMP ASSEMLOOP ; ; assemble the different parts into an instruction ; BUILDIT: MOV AL,BYTE PTR [AWORD] OR AL,AL JNZ BUILD1 BLDERR: JMP ASMERR BUILD1: DEC AL OR BYTE PTR [DI+1],AL ; SET THE SIZE BUILD2: CMP BYTE PTR [NUMFLG],0 ; TEST FOR IMMEDIATE DATA JZ BUILD3 CMP BYTE PTR [MEMFLG],0 JZ BLDERR BUILD3: MOV AL,BYTE PTR [REGMEM] CMP AL,-1 JZ BLD1 TEST AL,10000B ; TEST IF SEGMENT REGISTER JZ BLD1 CMP BYTE PTR [MOVFLG],0 JZ BLDERR MOV WORD PTR [DI+1],10001110B INC BYTE PTR [MOVFLG] INC BYTE PTR [SEGFLG] AND AL,00000011B SHL AL,1 SHL AL,1 SHL AL,1 OR AL,BYTE PTR 11000000B MOV BYTE PTR [DI+2],AL RET BLD1: AND AL,00000111B BLD4: OR AL,BYTE PTR [MODE] OR AL,BYTE PTR [MIDFLD] MOV BYTE PTR [DI+2],AL MOV AX,WORD PTR [LOWNUM] MOV WORD PTR [DI+3],AX RET GETREGMEM: MOV BYTE PTR [F8087],0 GETREGMEM2: CALL SCANP XOR AX,AX MOV WORD PTR [LOWNUM],AX ; OFFSET MOV WORD PTR [DIFLG],AX ; DIFLG+SIFLG MOV WORD PTR [BXFLG],AX ; BXFLG+BPFLG MOV WORD PTR [NEGFLG],AX ; NEGFLG+NUMFLG MOV WORD PTR [MEMFLG],AX ; MEMFLG+REGFLG DEC AL CMP BYTE PTR [F8087],0 JZ PUTREG MOV AL,1 ; DEFAULT 8087 REG IS 1 PUTREG: MOV BYTE PTR [REGMEM],AL GETLOOP:MOV BYTE PTR [NEGFLG],0 GETLOOP1: MOV AX,WORD PTR [SI] CMP AL,',' JZ GOMODE CMP AL,13 JZ GOMODE CMP AL,';' JZ GOMODE CMP AL,9 JZ GETTB CMP AL,' ' JNZ GOGET GETTB: INC SI JMP GETLOOP1 GOGET: JMP GETINFO ; ; DETERMINE THE MODE BITS ; GOMODE: MOV DI,OFFSET DG:ASSEM_CNT MOV BYTE PTR [MODE],11000000B MOV BYTE PTR [ASSEM_CNT],2 CMP BYTE PTR [MEMFLG],0 JNZ GOMODE1 MOV AL,[NUMFLG] OR AL,[REGFLG] JNZ MORET OR AL,[F8087] JZ ERRET MOV AL,[DI+1] OR AL,[DIRFLG] CMP AL,0DCH ; ARITHMETIC? JNZ MORET MOV BYTE PTR [DI+1],0DEH ; ADD POP TO NULL ARG 8087 MORET: RET ERRET: JMP ASMERR GOMODE1:MOV BYTE PTR [MODE],0 CMP BYTE PTR [NUMFLG],0 JZ GOREGMEM MOV BYTE PTR [DI],4 MOV AX,WORD PTR [DIFLG] OR AX,WORD PTR [BXFLG] JNZ GOMODE2 MOV BYTE PTR [REGMEM],00000110B RET GOMODE2:MOV BYTE PTR [MODE],10000000B CALL CHKSIZ1 CMP CL,2 JZ GOREGMEM DEC BYTE PTR [DI] MOV BYTE PTR [MODE],01000000B ; ; DETERMINE THE REG-MEM BITS ; GOREGMEM: MOV BX,WORD PTR [BXFLG] MOV CX,WORD PTR [DIFLG] XOR DX,DX GOREG0: MOV AL,BL ; BX ADD AL,CH ; SI CMP AL,2 JZ GOGO INC DL MOV AL,BL ADD AL,CL CMP AL,2 JZ GOGO INC DL MOV AL,BH ADD AL,CH CMP AL,2 JZ GOGO INC DL MOV AL,BH ADD AL,CL CMP AL,2 JZ GOGO INC DL OR CH,CH JNZ GOGO INC DL OR CL,CL JNZ GOGO INC DL ; BP+DISP OR BH,BH JZ GOREG1 CMP BYTE PTR [MODE],0 JNZ GOGO MOV BYTE PTR [MODE],01000000B INC BYTE PTR [DI] DEC DL GOREG1: INC DL ; BX+DISP GOGO: MOV BYTE PTR [REGMEM],DL RET GETINFO:CMP AX,'EN' ; NEAR JNZ GETREG3 GETREG0:MOV DL,2 GETRG01:CALL SETSIZ1 GETREG1:CALL SCANS MOV AX,WORD PTR [SI] CMP AX,"TP" ; PTR JZ GETREG1 JMP GETLOOP GETREG3:MOV CX,5 MOV DI,OFFSET DG:SIZ8 CALL CHKREG ; LOOK FOR BYTE, WORD, DWORD, ETC. JZ GETREG41 INC AL MOV DL,AL JMP GETRG01 GETREG41: MOV AX,[SI] CMP BYTE PTR [F8087],0 JZ GETREG5 CMP AX,"TS" ; 8087 STACK OPERAND JNZ GETREG5 CMP BYTE PTR [SI+2],"," JNZ GETREG5 MOV BYTE PTR [DIRFLG],0 ADD SI,3 JMP GETLOOP GETREG5:CMP AX,"HS" ; SHORT JZ GETREG1 CMP AX,"AF" ; FAR JNZ GETRG51 CMP BYTE PTR [SI+2],"R" JNZ GETRG51 ADD SI,3 MOV DL,4 JMP GETRG01 GETRG51:CMP AL,'[' JNZ GETREG7 GETREG6:INC BYTE PTR [MEMFLG] INC SI JMP GETLOOP GETREG7:CMP AL,']' JZ GETREG6 CMP AL,'.' JZ GETREG6 CMP AL,'+' JZ GETREG6 CMP AL,'-' JNZ GETREG8 INC BYTE PTR [NEGFLG] INC SI JMP GETLOOP1 GETREG8: ; LOOK FOR A REGISTER CMP BYTE PTR [F8087],0 JZ GETREGREG CMP AX,"TS" JNZ GETREGREG CMP BYTE PTR [SI+2],"(" JNZ GETREGREG CMP BYTE PTR [SI+4],")" JNZ ASMPOP MOV AL,[SI+3] SUB AL,"0" JB ASMPOP CMP AL,7 JA ASMPOP MOV [REGMEM],AL INC BYTE PTR [REGFLG] ADD SI,5 CMP WORD PTR [SI],"S," JNZ ZLOOP CMP BYTE PTR [SI+2],"T" JNZ ZLOOP ADD SI,3 ZLOOP: JMP GETLOOP GETREGREG: MOV CX,20 MOV DI,OFFSET DG:REG8 CALL CHKREG JZ GETREG12 ; CX = 0 MEANS NO REGISTER MOV BYTE PTR [REGMEM],AL INC BYTE PTR [REGFLG] ; TELL EVERYONE WE FOUND A REG CMP BYTE PTR [MEMFLG],0 JNZ NOSIZE CALL SETSIZ INCSI2: ADD SI,2 JMP GETLOOP NOSIZE: CMP AL,11 ; BX REGISTER? JNZ GETREG9 CMP WORD PTR [BXFLG],0 JZ GETOK ASMPOP: JMP ASMERR GETOK: INC BYTE PTR [BXFLG] JMP INCSI2 GETREG9: CMP AL,13 ; BP REGISTER? JNZ GETREG10 CMP WORD PTR [BXFLG],0 JNZ ASMPOP INC BYTE PTR [BPFLG] JMP INCSI2 GETREG10: CMP AL,14 ; SI REGISTER? JNZ GETREG11 CMP WORD PTR [DIFLG],0 JNZ ASMPOP INC BYTE PTR [SIFLG] JMP INCSI2 GETREG11: CMP AL,15 ; DI REGISTER? JNZ ASMPOP ; *** error CMP WORD PTR [DIFLG],0 JNZ ASMPOP INC BYTE PTR [DIFLG] JMP INCSI2 GETREG12: ; BETTER BE A NUMBER! MOV BP,WORD PTR [ASMADD+2] CMP BYTE PTR [MEMFLG],0 JZ GTRG121 GTRG119:MOV CX,4 GTRG120:CALL GETHX JMP SHORT GTRG122 GTRG121:MOV CX,2 CMP BYTE PTR [AWORD],1 JZ GTRG120 CMP BYTE PTR [AWORD],CL JZ GTRG119 CALL GET_ADDRESS GTRG122:JC ASMPOP MOV [HINUM],AX CMP BYTE PTR [NEGFLG],0 JZ GETREG13 NEG DX GETREG13: ADD WORD PTR [LOWNUM],DX INC BYTE PTR [NUMFLG] GETLOOPV: JMP GETLOOP CHKREG: PUSH CX INC CX REPNZ SCASW POP AX SUB AX,CX OR CX,CX RET STUFF_BYTES: PUSH SI LES DI,DWORD PTR ASMADD MOV SI,OFFSET DG:ASSEM_CNT XOR AX,AX LODSB MOV CX,AX JCXZ STUFFRET REP MOVSB MOV WORD PTR [ASMADD],DI STUFFRET: POP SI RET SETSIZ: MOV DL,1 TEST AL,11000B ; 16 BIT OR SEGMENT REGISTER? JZ SETSIZ1 INC DL SETSIZ1: CMP BYTE PTR [AWORD],0 JZ SETSIZ2 CMP BYTE PTR [AWORD],DL JZ SETSIZ2 SETERR: POP DX JMP ASMPOP SETSIZ2:MOV BYTE PTR [AWORD],DL RET ; ; DETERMINE IF NUMBER IN AX:DX IS 8 BITS, 16 BITS, OR 32 BITS ; CHKSIZ: MOV CL,4 CMP AX,BP JNZ RETCHK CHKSIZ1:MOV CL,2 MOV AX,DX CBW CMP AX,DX JNZ RETCHK DEC CL RETCHK: RET ; ; get first character after first space ; SCANS: CMP BYTE PTR [SI],13 JZ RETCHK CMP BYTE PTR [SI],"[" JZ RETCHK LODSB CMP AL," " JZ SCANBV CMP AL,9 JNZ SCANS SCANBV: JMP SCANB ; ; Set up for 8087 op-codes ; SETMID: MOV BYTE PTR [ASSEM1],0D8H MOV AH,AL AND AL,111B ; SET MIDDLE BITS OF SECOND BYTE SHL AL,1 SHL AL,1 SHL AL,1 MOV [MIDFLD],AL MOV AL,AH ; SET LOWER BITS OF FIRST BYTE SHR AL,1 SHR AL,1 SHR AL,1 OR [ASSEM1],AL MOV BYTE PTR [F8087],1 ; INDICATE 8087 OPERAND MOV BYTE PTR [DIRFLG],100B RET ; ; Set MF bits for 8087 op-codes ; SETMF: MOV AL,[AWORD] TEST BYTE PTR [DI+1],10B JNZ SETMFI AND BYTE PTR [DI+1],11111001B ; CLEAR MF BITS CMP AL,3 ; DWORD? JZ SETMFRET CMP AL,4 ; QWORD? JZ SETMFRET2 TEST BYTE PTR [DI+1],1 JZ SETMFERR CMP AL,5 ; TBYTE? JZ SETMFRET3 JMP SHORT SETMFERR SETMFI: CMP AL,3 ; DWORD? JZ SETMFRET CMP AL,2 ; WORD? JZ SETMFRET2 TEST BYTE PTR [DI+1],1 JZ SETMFERR CMP AL,4 ; QWORD? JNZ SETMFERR OR BYTE PTR [DI+1],111B SETMFRET3: OR BYTE PTR [DI+1],011B OR BYTE PTR [DI+2],101000B JMP SHORT SETMFRET SETMFRET2: OR BYTE PTR [DI+1],100B SETMFRET: RET SETMFERR: JMP ASMPOP DW_OPER: MOV BP,1 JMP SHORT DBEN DB_OPER: XOR BP,BP DBEN: MOV DI,OFFSET DG:ASSEM_CNT DEC BYTE PTR [DI] INC DI DB0: XOR BL,BL CALL SCANP JNZ DB1 DBEX: JMP ASSEM_EXIT DB1: OR BL,BL JNZ DB3 MOV BH,BYTE PTR [SI] CMP BH,"'" JZ DB2 CMP BH,'"' JNZ DB4 DB2: INC SI INC BL DB3: LODSB CMP AL,13 JZ DBEX CMP AL,BH JZ DB0 STOSB INC BYTE PTR [ASSEM_CNT] JMP DB3 DB4: MOV CX,2 CMP BP,0 JZ DB41 MOV CL,4 DB41: PUSH BX CALL GETHX POP BX JNC DB5 JMP ASMERR DB5: MOV AX,DX CMP BP,0 JZ DB6 STOSW INC BYTE PTR [ASSEM_CNT] JMP SHORT DB7 DB6: STOSB DB7: INC BYTE PTR [ASSEM_CNT] JMP DB0 CODE ENDS END ASSEM