; CP/M DEBUGGER DISASSEMBLER/ASSEMBLER MODULE TITLE 'SYMBOLIC INTERACTIVE DEBUGGER (ASMOD) 12/16/77' ; ; COPYRIGHT (C) 1976, 1977 ; DIGITAL RESEARCH ; BOX 579 PACIFIC GROVE, CA ; 93950 ; FALSE EQU 0 ;VALUE OF "FALSE" TRUE EQU NOT FALSE ;VALUE OF "TRUE" ISIS2 EQU FALSE ;TRUE IF ASSEMBLING FOR "IS" DEBUG EQU FALSE ;TRUE IF CHECK-OUT TIME RELOC EQU TRUE ;TRUE IF GENERATING RELOC IMAGE ; IF DEBUG ORG 1000H ;IN LOW MEMORY FOR DEBUG ELSE IF ISIS2 ORG 0E500H ELSE IF RELOC ORG 0000H ;READY FOR RELOCATION ELSE ORG 0D000H ;DEBUG IN 64K ENDIF ENDIF ENDIF ; JLOC1 EQU 0005H ;BDOS JUMP LOCATION ; ; ; ENTRY POINTS FOR DEBUGGING MONITOR DEMON EQU $+680H BEGIN EQU DEMON+03H ;BEGINNING OF DEBUGGING MONITOR GETBUFF EQU DEMON+9H ;READ BUFFER GNC EQU DEMON+0CH PCHAR EQU DEMON+0FH ;PRINT CHARACTER IN REG A PBYTE EQU DEMON+12H ;PRINT BYTE PADDX EQU DEMON+15H ;PRINT ADDRESS IN REG D,E SCANEXP EQU DEMON+18H ;SCAN 0,1, OR 2 EXPRESSIONS BREAK EQU DEMON+1EH ;CHECK FOR BREAK AT CONSOLE PRLABEL EQU DEMON+21H ;PRINT SYMBOLIC LABEL ; ; CI EQU GNC ;SYNONYM FOR GNC ; CR EQU 0DH LF EQU 0AH TAB EQU 09H ; MODLOC: ;MODULE LOCATION JMP BEGIN ;ADDRESS FIELD IS ALTERED AT "BEGIN" DB 0,0,0 ;FILLER (USED IN SYMBOL TABLE) JMP DISENT JMP ASMEN ;ENTRY POINT FOR ASSEMBLER PC: DS 2 ;CURRENT FAKED PC DURING DISASSEMBLY MPC: DS 2 ;MAX VALUE FOR PC (STOP ADDRESS) PAGM: DS 1 ;PAGE MODE IF NON ZERO TPC: DS 2 ;TEMPORARY PC FOR ASSEMBLER RESTORE ON ERROR OLDSP: DS 2 ;ENTRY SP VALUE ; ; CO: ;PRINT CHARACTER IN REGISTER C PUSH PSW MOV A,C ;PCHAR EXPECTS VALUE IN C CALL PCHAR ;TO PRINT THE CHARACTER POP PSW RET ; ; DELIM: ;CHECK FOR DELIMITER CPI ' ' RZ CPI TAB RZ CPI ',' RZ CPI CR RZ CPI 7FH JZ ASMEN ;RESTART CURRENT LINE RET ; CRLF: ;RETURN AND LINE FEED MVI C,CR CALL CO MVI C,LF CALL CO RET ; SCAN: ;FILL OPCODE WITH CHARACTERS ; SC1: CALL CI SCAN0: ;ENTER HERE IF CHARACTER SCANNED CPI CR JZ ERR CALL DELIM JZ SC1 ; ; CLEAR BUFFER MVI C,4 LXI H,OPCODE SC0: MVI M,' ' INX H DCR C JNZ SC0 ; ; GARBAGE REMOVED AT BEGINNING OF SCAN MVI C,5 LXI H,OPCODE SC2: MOV M,A ;STORE CHARACTER CALL CI CALL DELIM JZ SC3 INX H DCR C JZ ERR ;TOO LONG JMP SC2 ; SC3: ;END OF CURRENT SCAN, COMPARE FOR EMPTY LDA OPCODE CPI ' ' RET ; HEX: ;CONVERT ACCUMULATOR TO HEXADECIMAL SUI '0' CPI 10 RC ;'0' - '9' ADI ('0'-'A'+10) AND 0FFH CPI 16 RC JMP ERR ; GADDR: ;GET ADDRESS VALUE TO B (HIGH ORDER) AND C (LOW) WITH COPY OF C IN A CALL SCANEXP ;READ 1 EXPRESSION DCR A ;GOES TO ZERO JNZ ERR ;? IF NOT A SINGLE EXPRESSION XCHG ;ADDRESS OF EXPRESSION TO HL MOV C,M ;LOW BYTE INX H MOV B,M ;HIGH BYTE MOV A,C ;COPY OF LOW BYTE TO A DCR B INR B ;SETS ZERO FLAG IF B IS ZERO RET ; GBYTE: ;GET BYTE VALUE TO ACCUMULATOR AND C, CHECK FOR HIGH ORDER ZERO CALL GADDR JNZ ERR RET ; ; ; ************************************************************ ; ********* ASSEMBLER MODULE STARTS HERE ********************* ; ************************************************************ ; ADJ: ;MOVE REGISTER INDICATOR TO MIDDLE FIELD OF CODE RAL RAL RAL ANI 111000B RET ; ADJ4: ;MOVE TO LEFT BY 4 AND MASK RAL RAL RAL RAL ANI 110000B RET ; SEAR2: ;SAME AS SEAR, EXCEPT 2 CHARACTER MATCH ; H,L ADDRESS TABLE TO MATCH ON XCHG LHLD OPCODE ;2ND BYTE IN D, 1ST BYTE IN E XCHG ;H,L ADDRESS TABLE SEA0: MOV A,E ;GET 1ST BYTE CMP M ;MATCH? JNZ SEA1 ;TO ADDRESS NEXT ELT INX H ;NEXT TO MATCH MOV A,D ;2ND CHAR CMP M RZ ;MATCH AT CURRENT ENTRY DCX H SEA1: DCX H DCX H ;ADDRESSES NEXT ELEMENT DCR C JNZ SEA0 ;FOR ANOTHER COMPARE ; ; NO MATCH IN TABLE, RETURN WITH NON-ZERO VALUE DCR C RET ; ; SEAR: ;SEARCH FOR MATCH IN OPCODE TABLE, LENGTH OF TABLE IN REG-C ; D,E CONTAINS ADDRESS OF BINARY EQUIVALENT OF OPCODE ; H,L ADDRESS FOUR CHARACTER OPCODE TO MATCH ; OPCODE CONTAINS FOUR BYTE OPCODE TYPED AT CONSOLE ; RETURNS WITH ZERO VALUE IF OPCOE FOUND, WITH D,E ; ADDRESSING PROPER BYTE, NON-ZERO IF NOT FOUND. MVI B,4 ;4 CHARACTER MATCH ; PUSH D ;SAVE THE CURRENT BYTE VALUE LOCATION LXI D,OPCODE ;ADDRESS CHARACTERS TYPED SE1: LDAX D ;POINT TO FIRST BYTE TO MATCH CMP M ;SAME CHARACTER AS TABLE? JNZ SE2 ;NO, SKIP TO NXT TABLE ENTRY INX H ;YES, LOOK AT NEXT CHARACTER INX D ;MOVE TO NEXT CHARACTER TYPED DCR B ;DECREMENT CHARACTER COUNT JNZ SE1 ;MORE TO MATCH? ; ; COMPLETE MATCH, RETURN WITH D,E ADDRESSING BYTE VALUE POP D RET ; ; MISMATCH, FINISH COUNT SE2: INX H DCR B JNZ SE2 ; ; H,L AT END OF FOUR BYTE AREA, MOVE BACK 8 LXI D,-8 DAD D ;H,L READY FOR NXT MATCH ; POP D ;RESTORE BYTE POINTER INX D ;MOVE TO NEXT IN CASE MATCH OK DCR C ;MORE OPCODES TO MATCH? JNZ SEAR ;LOOK FOR MORE ; ; NO MATCH FOUND IN TABLE, SET NON-ZERO VALUE AND RETURN DCR C RET ; ; GETREG: ;SCAN FOR SIMPLE REGISTER REFERENCE PUSH B CALL SCAN JZ ERR MVI C,8 ;8 REGISTERS LXI H,SREG ;SIMPLE REGISTERS CALL SEAR2 ;LOOK FOR 2 CHAR MATCH JNZ ERR DCR C MOV A,C POP B RET ; GETD: ;GET DOUBLE PRECISION REGISTER PUSH B CALL SCAN JZ ERR MVI C,5 LXI H,DREG CALL SEAR JNZ ERR DCR C MOV A,C POP B RET ; GETDR: ;GET DOUBLE REGISTER (BDHSP) CALL GETD CPI 4 ;PSW? JZ ERR RET ; GETPR: ;GET PUSH/POP REGISTER (BDH OR PSW) CALL GETD CPI 3 JZ ERR CPI 4 RNZ DCR A ;PSW MUST BE ADJUSTED RET ; GCON: ;GET CONDITION CODE ; BUFFER IS SCANNED, MOVE LEFT BEFORE COMPARE LXI H,OPCODE LXI D,OPCODE+1 MVI C,2 ;MOVE TWO CHARACTERS MOP: LDAX D ;LOAD CHARACTER TO MOVE MOV M,A ;MOVE LEFT INX H ;NEXT DESTINATION INX D ;NEXT SOURCE DCR C JNZ MOP ; ; MUST BE BLANK AT END LDAX D CPI ' ' JNZ ERR MOV M,A ; ; NOW READY TO DO THE COMPARE LXI H,CREG MVI C,8 CALL SEAR2 JNZ ERR DCR C MOV A,C CALL ADJ ;MOVE TO BITS 3,4,5 OF BYTE (LSB = 0) RET ; GCONA: ;GET CONDITION CODE TO REGISTER A, DOUBLE ADDRESS TO B,C CALL GCON ;CONDITION CODE TO A PUSH PSW CALL GADDR ;VALUE TO B,C POP PSW ; INCLUDE HIGH ORDER 11'S FOR J AND C OPCODES ORI 11000000B RET ; SETMD: ;SET MEMORY AT LOCATION PC TO VALUE ADDRESSED BY D LDAX D ;VALUE TO ACCUM ; SETM: ;SET MEMORY AT LOCATION PC TO VALUE IN ACCUM, INC PC LHLD TPC MOV M,A ;STORE AT PC INX H ;PC=PC+1 SHLD TPC RET ; ; ; GETOP: ;PROCESS NEXT OPCODE CALL CI CPI CR JZ GOBACK ;RETURN IF SIMPLE INPUT CPI '.' ;ALTERNATE RETURN IS . JZ GOBACK CALL SCAN0 JZ ERR ; CHK0: ;CHECK FOR OPCODES WITH NO OPERANDS MVI C,17 ;LENGTH OF GROUP-0 LXI H,ETAB1 ;END OF GROUP-0 LXI D,TABLE ;FIRST BYTE VALUE CALL SEAR ;LOOK FOR MATCH JNZ CHK1 ;NO MATCH, CHECK FOR GROUP-1 ; ; MATCHED OPCODE, D,E ADDRESS BYTE VALUE JMP SETMD ;SET MEMORY AT PC AND INC PC ; ; CHECK GROUP-1 VALUES CHK1: MVI C,10 ;LENGTH OF GROUP-1 LXI H,ETAB2 CALL SEAR ;D,E REMAIN SET JNZ CHK2 ;NO MATCH, CHECK NEXT GROUP ; ; MATCH FOUND, SET BYTE AND GET BYTE OPERAND CALL SETMD CALL GBYTE ;GETS BYTE VALUE TO ACCUMULATOR JMP SETM ;PUTS BYTE VALUE TO MEMORY AT PC ; ; CHECK GROUP-2 OPCODES, REQUIRE DOUBLE BYTE OPERAND CHK2: MVI C,6 LXI H,ETAB3 CALL SEAR JNZ CHK3 ;NO MATCH ; ; FOUND MATCH, GET OPCODE BIT PATTERN AND STORE CALL SETMD OP2: ;ENTER HERE FOR DOUBLE BYTE OPERANDS CALL GADDR ;VALUE IN B,A CALL SETM MOV A,B JMP SETM ; CHK3: ;CHECK FOR MOV INSTRUCTION MVI C,1 LXI H,PMOV CALL SEAR JNZ CHK4 ; ; MOV INSTRUCTION GET DESTINATION OPERAND CALL GETREG ;VALUE TO ACCUMULATOR CALL ADJ MOV B,A ;SAVE IN B MVI C,01000000B ;BIT PATTERN FOR MOV ; OP1: ;GET NEXT OPERAND FOR MOV, FIRST OPERAND FOR ACCUM/REG OPERATOR CALL GETREG ORA C ;SETS HIGH ORDER TWO BITS ORA B ;SETS DESTINATION/OPERATOR JMP SETM ; CHK4: ;CHECK FOR GROUP-5 (ACCUM/REG OPERATOR) MVI C,8 LXI H,ETAB5 CALL SEAR JNZ CHK5 ; ; ACCUM/REG INSTRUCTION, C COUNTS OPERATORS AS SEARCH PROCEEDS DCR C MOV A,C CALL ADJ MOV B,A ; OPERATOR NUMBER (SHIFTED) SAVED FOR LATER MASK MVI C,10000000B ;ACCUM/REG OPERATOR INDICATOR JMP OP1 ;GETS OPERAND AND SAVES BYTE IN MEMORY ; CHK5: ;MAY BE INR/DCR MVI C,2 LXI H,PDCR CALL SEAR JNZ CHK6 ; ; C=2 IF DCR, =1 IF INR INR C ;+1 INR C ;+2 INR C ;+3 CALL GETREG ;VALUE TO ACCUM CALL ADJ ORA C ;FILL PROPER INSTRUCTION INDICATOR JMP SETM ; CHK6: ;MAY BE A MVI INSTRUCTION MVI C,1 LXI H,PMVI CALL SEAR JNZ CHK7 ; ; MVI INSTRUCTION, GET REGISTER CALL GETREG ;VALUE GOES TO ACCUMULATOR CALL ADJ ORI 110B CALL SETM CALL GBYTE JMP SETM ; CHK7: ;CHECK FOR GROUP-7 MVI C,6 LXI H,ETAB7 CALL SEAR JNZ CHK8 ; ; LXI,STAX,INX,DAD,LDA, OR DCX MOV A,C ;A=1...6 CPI 4 JC IN0 ; ; MUST BE DAD,LDA, OR DCX ADI 5 ;CHANGES ACCUM TO 9,10, OR 11 IN0: ;ACCUMULATOR CONTAINS CODE, SAVE IT MOV B,A CALL GETDR ;DOUBLE REGISTER VALUE TO ACCUM CALL ADJ4 ;ADJUST VALUE TO MIDDLE FIELD ORA B ;FILLS REMAINING BITS CALL SETM ; MAY BE LXI ANI 11001111B CPI 1 RNZ ;NOT LXI JMP OP2 ;PICK UP OPERAND ; ; ; CHK8: ;RST? MVI C,1 LXI H,PRST CALL SEAR JNZ CHK9 ; ; RST, GET OPERAND CALL GBYTE CPI 8 JNC ERR CALL ADJ ORI 11000111B JMP SETM ; CHK9: ;POP/PUSH? MVI C,2 LXI H,PPOP+4 CALL SEAR JNZ CHK10 ; ; C=2 IF PUSH, 1 IF POP DCR C JNZ PP0 ; ; POP, SET BIT PATTERN MVI C,11000001B JMP PP1 ; PP0: ;PUSH MVI C,11000101B PP1: CALL GETPR ;DOUBLE PUSH/POP REGISTER TO PROPER FIELD CALL ADJ4 ;MOVE TO FIELD ORA C JMP SETM ; CHK10: ;J/C/R? LDA OPCODE CPI 'J' JNZ CHK11 CALL GCONA ; CONDITION CODE TO FIELD IN ACCUM, ADDRESS TO B,C ORI 010B JMP FADDR ;FILL ADDRESS ; CHK11: CPI 'C' JNZ CHK12 CALL GCONA ORI 100B ; FADDR: CALL SETM MOV A,C CALL SETM MOV A,B JMP SETM ; CHK12: CPI 'R' JNZ ERR CALL GCON ORI 11000000B JMP SETM ; ; ************************************************************ ; *********** END OF ASSEMBLER MODULE, START DISASSEMBLER **** ; ************************************************************ ; RDBYTE: LHLD MPC PUSH D ;SAVE DE XCHG ;MAX PC TO D,E LHLD PC ;CURRENT PC ; SUBTRACT PC FROM MPC, STOP IF CARRY GENERATED MOV A,E SUB L MOV A,D SBB H JNC RD0 ; ; PC EXCEEDS MPC, RETURN LHLD OLDSP SPHL ;RESTORE ORIGINAL STACK POINTER RET ; RD0: POP D ;RESTORE D,E MOV A,M INX H SHLD PC RET RGPRNT: INR A ANI 07 CPI 06 JC RGP1 ADI 03 RGP1: CPI 05 JC RGP2 ADI 02 RGP2: ADI 41H MOV C,A JMP CO DECODE: MOV B,A ANI 0F0H RRC RRC RRC RRC ADI 90H DAA ACI 40H DAA MOV C,A CALL CO MOV A,B ANI 0FH ADI 90H DAA ACI 40H DAA MOV C,A JMP CO PRINT: MVI B,4 P1: MOV C,M CALL CO INX H DCR B JNZ P1 MVI C,' ' JMP CO ; ; EXTRACT THE REGISTER FIELD FROM THE OPCODE XTRACT: MOV A,D ANI 0011$1000B RRC RRC RRC RET ; ; PRINT CONDITION CODE CCPRNT: CALL XTRACT ADD A MOV C,A LXI H,CCODE DAD B MOV C,M CALL CO INX H MOV C,M CALL CO MVI C,' ' CALL CO JMP CO ; PRINT REGISTER REFERENCE RPPRNT: CALL XTRACT ANI 06 CPI 06 JNZ RGPRNT MVI C,'S' CALL CO MVI C,'P' JMP CO ; ; PRPC: ;PRINT CRLF FOLLOWED BY PC VALUE CALL CRLF ; (ENTER HERE FROM DISASSEMBLER) PRPC0: LHLD PC MOV A,H CALL DECODE MOV A,L CALL DECODE MVI C,' ' CALL CO CALL CO RET ; DISENT: ;ENTER HERE FROM DEBUGGER LXI H,0 DAD SP SHLD OLDSP ;SP SAVED FOR LATER RETURN ; ; CHECK FOR PAGE MODE DISPLAY LDA PAGM ;GET PAGE MODE (NUMBER OF LINES TO PRINT) ORA A ;SET FLAGS JZ DISASM ;NOT PAGE MODE ; ; SET MPC TO 0FFFFH LXI H,0FFFFH SHLD MPC ; 255 IMPLIES TRACE MODE INR A JNZ DISASM ;NOT TRACE MODE IF BR ; TRACE MODE, SET TO 1 AND IGNORE ADDRESS FIELD INR A ;1 IN ACC STA PAGM LHLD PC ;RECOVER PC JMP DIS1 ; ; DISASM: ; CHECK FOR BREAK AT CONSOLE CALL BREAK JNZ GOBACK ; ; CHECK TO SEE IF ENOUGH LINES PRINTED IN PAGE MODE LXI H,PAGM MOV A,M ORA A ;ZERO? JZ DIS0 ;JMP IF NOT PAGE MODE ; ; PAGE MODE, DECREMENT AND CHECK FOR ZERO DCR M JZ GOBACK ; DIS0: LHLD PC ;CURRENT PC CALL PRLABEL ;OPTIONAL LABEL CALL CRLF ;NEW LINE MVI C,' ' CALL CO CALL CO ;TWO LEADING BLANKS CALL PRPC0 ;PRINT THE VALUE DIS1: CALL RDBYTE ; SAVE THE OPCODE IN THE D REGISTER MOV D,A ; SEARCH THE FIRST 17 ITEMS FOR SIMPLE OPCODES ; EI (FB) THROUGH NOP (00). NOTE THAT THE SEARCH PROCEEDS ; THROUGH "TABLE" STARTING AT THE BEGINNING, BUT THE OPCODES ; ARE ACTUALLY STORED IN SYMBOLIC FORM IN REVERSE ORDER. ; LXI H,TABLE LXI B,17 ;FIRST 17 SIMPLE OPCODES GROUP1: CMP M ;TABLE VALUE = OPCODE? JZ TYPE1 ;SKIP TO PRINT IF SO INX H ;MOVE TO THE NEXT TABLE ELEMENT DCR C ;COUNT THE SIMPLE OPCODES DOWN JNZ GROUP1 ;TRY FOR ANOTHER ; ; NOT A SIMPLE OPERATION CODE, CHECK FOR IMMEDIATE OP ; ADI, ACI, OUT, SUI, IN, SBI, ANI, XRI, ORI, CPI MVI C,10 GROUP2: CMP M JZ TYPE2 INX H DCR C JNZ GROUP2 ; ; NOT AN IMMEDIATE OPERATION, CHECK FOR ; SHLD LHLD STA LDA JMP OR CALL MVI C,6 GROUP3: CMP M JZ TYPE3 INX H DCR C JNZ GROUP3 ; ; NOT TYPE3 OPERATION CODE, CHECK FOR MOV ; BY MASKING THE HIGH ORDER TWO FIBITS - ; XX00 0000 IS PRODUCED IN THE ACCUMULATOR ANI 0C0H ; MOV IS GIVEN BY 01 DDD SSS (DDD IS DEST, SSS IS SOURCE) CPI 40H JZ MOVOP ; ; NOT A MOV INSTRUCTION, CHECK FOR ACCUMLATOR-REGISTER OPS ; BIT PATTERN 10 CCC RRR CORRESPONDS TO ; ADD (0), ADC (1), SUB (2), SBB (3), ANA (4), ; XRA (5), ORA (6), CMP (7) CPI 80H JZ ACCREG ; ; NOT ACCUM-REGISTER, RESTORE OPCODE FOR FURTHER CHECKS MOV A,D ; ; LOOK FOR INR, DCR, AND MVI OPERATIONS ; INR = 00 RRR 100, DCR = 00 RRR 101, MVI = 00 RRR 110 ; OR, INR = 00 RRR 4, DCR = 00 RRR 5, MVI = 00 RRR 6 ANI 1100$0111B SUI 04 ; INR GOES TO ZERO JZ INRREG ; NOT INR, MAY BE DCR DCR A JZ DCRREG DCR A ; NOT DCR, MAY BE MVI JZ MVIREG ; NOT INR, DCR, OR MVI INSTRUCTION ; ; RESTORE THE OPCODE MOV A,D ; LOOK FOR LXI STAX INX DAD LDAX DCX OPCODES ; LXI = 00 RR 0001, ; STAX= 00 RR 0010, ; INX = 00 RR 0011, ; DAD = 00 RR 1001, ; LDAX= 00 RR 1010 ; DCX = 00 RR 1011 ANI 0C0H JZ LXILST ;TO PROCESS FURTHER ; ; NOT ONE OF THE ABOVE, CHECK FURTHER ; MUST BE OF THE FORM - 11 XXX XXX MOV A,D ANI 0000$0111B ;TO EXTRACT THE RIGHTMOST BITS ; RETURN CONDITIONALS TAKE THE FORM 11 XXX 000 JZ RETCON ;RETURN CONDITIONALLY ; JUMP CONDITIONALS TAKE THE FORM 11 XXX 010 = 2 SUI 02 JZ JMPCON ; CALL CONDITIONALS TAKE THE FORM 11 XXX 100 = 4 - 2 = 2 SUI 02 JZ CALLCON ; RST'S TAKE THE FORM 11 XXX 111 = 7 - 4 = 3 SUI 03 JZ RSTOP ; ; NONE OF THE ABOVE, PUSHES AND POP'S REMAIN MOV A,D ;RESTORE OPCODE ; FIRST CAPTURE REMAINING OPCODES CB, D9, DD, ED, FD ANI 0000$1000B ;THIS BIT RESET FOR POP,PUSH JNZ N8080 ;NOT 8080 OPCODE IF SET MOV A,D ;RESTORE IT ; PUSH = 11 XX0 101 = 5, POP = 11 XX0 001 = 1 ANI 07 ; USE THE RESULTING VALUE TO INDEX TO REGISTER TABLE MOV C,A DCR A ;POP GOES TO 00 LXI H,PPOP-1 DAD B CALL PRINT ; GET THE RELEVANT REGISTER CALL XTRACT ; CHECK FOR PSW OPERATION CODE CPI 06 JNZ D6 LXI H,PPSW CALL PRINT JMP DISASM ; ; PRINT RST XXX INSTRUCTION RSTOP: LXI H,PRST CALL PRINT CALL XTRACT CALL DECODE JMP DISASM ; ; CALL CONDITIONAL 'C' CALLCON: MVI C,'C' CALL CO CALL CCPRNT JMP PREXT ;TO PRINT THE ADDRESS ; ; JUMP CONDITIONAL 'J' JMPCON: MVI C,'J' CALL CO CALL CCPRNT JMP PREXT ;TO PRINT THE ADDRESS ; ; RETURN CONDITIONAL 'R' RETCON: MVI C,'R' CALL CO CALL CCPRNT JMP DISASM ; ; ; PROCESS ONE OF LXI STAX INX DAD LDAX DCX LXILST: LXI H,PLXI ; CAPTURE 08, 10, 18, 20, 28, 30, AND 38 MOV A,D ;GET OPCODE ANI 111B ;RIGHTMOST BITS ZERO? JZ N8080 ;NOT 8080 IF SO ; RECALL OPCODE TO DETERMINE WHICH ONE MOV A,D ; FIND THE PARTICULAR OPCODE ANI 0FH ; LXI HAS LEAST SIGNIFICANT FOUR BITS = 0001 DCR A JZ LXIREG ; STAX 0010 BECOMES 0001 = 1 ; INX 0011 BECOMES 0010 = 2 ; DAD 1001 BECOMES 1000 = 8 ; LDAX 1010 BECOMES 1001 = 9 ; DCX 1011 BECOMES 1010 = 10 CPI 03 JC D4 ; MUST BE DAD, LDAX OR DCX SUI 05 ; DAD 8 BECOMES 3 ; LDAX9 BECOMES 4 ; DCX10 BECOMES 5 ; ACCUMULATOR NORMALIZED D4: ADD A ADD A ; VALUE IN ACCUM MULTIPLIED BY FOUR MOV C,A DAD B CALL PRINT ; STAX, INX, DAD, LDAX, OR DC X PRINTED, PRINT REGISTER CALL RPPRNT JMP DISASM ; ; PRINT REGISTER ADDRESSED BY HL (E.G., IN LXI) LXIREG: CALL PRINT CALL RPPRNT MVI C,',' CALL CO JMP PREXT ;TO PRINT THE EXTENDED INSTRUCTION ; ; MVIREG: LXI H,PMVI CALL PRINT CALL XTRACT CALL RGPRNT MVI C,',' CALL CO JMP DATA8 ; DCRREG: LXI H,PDCR JMP D5 ; INRREG: LXI H,PINR ; ; PRINT THE INSTRUCTION GIVEN BY HL, FOLLOWED BY REGISTER D5: CALL PRINT CALL XTRACT D6: CALL RGPRNT JMP DISASM ; ; FOUND ACCUM REGISTER OPERATION - MIDDLE BITS GIVE PCODE ACCREG: MOV A,D ANI 38H ;SELECT OPCODE BITS RRC ;OPCODE * 4 FOR LENGTH FOUR STRING MOV C,A LXI H,PADD ;ADDRESS THE ACCUM-REGISTER LIST DAD B CALL PRINT JMP D9 ; ; MOV OPERATION FOUND MOVOP: LXI H,PMOV CALL PRINT CALL XTRACT CALL RGPRNT MVI C,',' ;REGISTER DELIMITER CALL CO D9: MOV A,D ANI 07 CALL RGPRNT JMP DISASM ; ; TYPE GROUP3: CALL JMP LDA STA LHLD SHLD TYPE3: MOV A,C ;*4 FOR LENGTH 4 ADD A ADD A MOV C,A LXI H,TAB3-4 DAD B CALL PRINT ; ; ARRIVE HERE TO PRINT THE ADDRESS FIELD PREXT: CALL RDBYTE ;LOW ADDRESS TO A PUSH PSW ;SAVE IT CALL RDBYTE MOV D,A ;SET HIGH ADDRESS POP PSW ;RECALL LOW ADDRESS MOV E,A ;DE IS THE ADDRESS TO PRINT CALL PADDX JMP DISASM ; ; TYPE THE IMMEDIATE OPCODES (INCLUDING IN/OUT) TYPE2: MOV A,C ;TYPE IMMEDIATE OPERATION CODE ADD A ;*2 ADD A ;*4 FOR LENGTH FOUR CHAR STRING MOV C,A ;BC = INDEX * 4 FOR OPCODE LXI H,TAB2-4 DAD B CALL PRINT ; ; ARRIVE HERE TO PRINT THE IMMEDIATE VALUE DATA8: CALL RDBYTE CALL PBYTE ;BYTE VALUE PRINTED JMP DISASM ; ; FOUND OPCODE IN TABLE, POSITION GIVEN ; BY COUNT IN BC (NOTE THAT C IS COUNTED DOWN, WHILE ; INDEX WAS MOVING UP THE TABLE DURING THE SEARCH) TYPE1: MOV A,C ;TYPE SIMPLE OPCODES FROM GROUP 1 ADD A ;POSITION * 2 ADD A ;POSITION * 4 (FOUR CHAR CODES) MOV C,A ;BC IS INDEX * 4 OF OPCODE LXI H,TAB1-4 DAD B ;HL NOW HOLDS ADDRESS OF CODE TO PRINT CALL PRINT JMP DISASM ; N8080: ;NOT AN 8080 OPERATION CODE LXI H,DBOP CALL PRINT ;PRINT THE '??=' MOV A,D ;GET THE OPCODE CALL PBYTE ;AND PRINT IT JMP DISASM ; ERR: ;ENTER HERE FOR ERROR REPORTING CALL CRLF MVI C,'?' CALL CO ; LHLD OLDSP SPHL ; PC REMAINS UNCHANGED ; ; ASMEN: ;ENTER HERE FROM DEBUGGER LXI H,0 DAD SP SHLD OLDSP ; ASM0: CALL PRPC ;PRINT PC VALUE SHLD TPC ;SAVE PC VALUE CALL GETBUFF ;FILL INPUT BUFFER CALL GETOP ;GET OPERATION ; UPDATE PC, MUST BE CORRECT INPUT LHLD TPC SHLD PC JMP ASM0 ; GOBACK: LHLD OLDSP SPHL RET ; ; THE FIRST 17 ITEMS CORRESPOND TO SIMPLE OPCODES ; (NOP BACKWARD THROUGH EI) TABLE: DB 000H,007H,00FH,017H ;NOP RLC RRC RAL DB 01FH,027H,02FH,037H ;RAR DAA CMA STC DB 03FH,076H,0C9H,0E3H ;CMC HLT RET XTHL DB 0E9H,0EBH,0F3H,0F9H ;PCHL XCHG DI SPHL DB 0FBH ;EI ; ; THE NEXT 10 ITEMS CORRESPOND TO THE IMMEDIATE OPCODES DB 0C6H,0CEH,0D3H ;ADI ACI OUT DB 0D6H,0DBH,0DEH,0E6H ;SUI IN SBI ANI DB 0EEH,0F6H,0FEH ;XRI ORI DB 022H ;SHLD DB 02AH,032H,03AH,0C3H DB 0CDH TAB1: DB 'EI ','SPHL','DI ','XCHG' DB 'PCHL','XTHL','RET ','HLT ' DB 'CMC ','STC ','CMA ','DAA ' DB 'RAR ','RAL ','RRC ','RLC ' ETAB1: DB 'NOP ' TAB2: DB 'CPI ','ORI ','XRI ','ANI ' DB 'SBI ','IN ','SUI ','OUT ' DB 'ACI ' ETAB2: DB 'ADI ' ; TAB3: DB 'CALL','JMP ','LDA ','STA ' DB 'LHLD' ETAB3: DB 'SHLD' ; PMOV: DB 'MOV ' PADD: DB 'ADD ','ADC ','SUB ','SBB ' DB 'ANA ','XRA ','ORA ' ETAB5: DB 'CMP ' PINR: DB 'INR ' PDCR: DB 'DCR ' PMVI: DB 'MVI ' PLXI: DB 'LXI ','STAX','INX ','DAD ' DB 'LDAX' ETAB7: DB 'DCX ' ; PRST: DB 'RST ' PPSW: DB 'PSW ' PPOP: DB 'POP ','PUSH' CCODE: DB 'NZ','Z ','NC','C ' DB 'PO','PE','P ' CREG: DB 'M ' DB 'B ','C ','D ','E ' DB 'H ','L ','M ' SREG: DB 'A ' ; DB 'B ','D ','H ','SP ' DREG: DB 'PSW ' ; DBOP: DB '??= ' OPCODE: DS 4 END