; Begin Program LXI SP,STACK+26 ; Initialize stack pointer CALL LOC ; Get starting address XRA A ; A=0 STA STACK+1 ; Put program into single step ; Begin Execution of Next Instruction, HL = Instruction Address Next: LXI SP,STACK+22 ; Set stack pointer to PSW XRA A ; A=0 STA INST ; Store NOP instruction STA INST+1 ; Store NOP instruction MOV A,M ; Load instruction ANI 0E7H ; Zero out bits 3 and 4 CPI 22H JZ THRB ; Jump if LHLD, SHLD, LDA, ; or STA MOV A,M ; Load instruction ANI 0CFH ; Zero out bits 4 and 5 CPI 1 JZ THRB ; Jump if LXI ANI 0C7H ; Zero out bits 3, 4, and 5 CPI 6 JZ TWOB ; Jump if MVI CPI 0C7H JZ ERST ; Jump if RST CPI 0C0H ; One byte instruction? JC ONEB ; Jump if less than C0 CPI 0C6H JZ TWOB ; Jump if two byte 'immediate' MOV A,M ; Load Instruction CPI 0F9H JZ ONEB ; Jump if SPHL CPI 0E9H JZ EPCHL ; Jump if PCHL ANI 0F7H ; Zero out bit 3 CPI 0D3H JZ TWOB ; Jump if IN or OUT ANI 0E7H ; Zero out bits 3 and 4 CPI 0E3H JZ ONEB ; Jump if XCHG, XTHL, EI, or DI MOV A,M ; Load instruction ANI 0CBH ; Zero out bits 2, 4, and 5 CPI 0C1H JZ ONEB ; Jump if POP or PUSH MOV A,M ; Load instruction CPI 0C3H JZ EXEC1 ; Jump if JMP CPI 0CDH JZ EXEC1 ; Jump if CALL CPI 0C9H JZ ERET ; Jump if RET ANI 38H ; Zero out bits 0, 1, 2, 6, and 7 RRC MOV C,A ; Save in C RRC ADD C ; form values 0, 6, 12, ... 48 (decimal) MOV C,A ; Save in C MVI B,0 ; B=0 XCHG ; Save PC value in DE LXI H,COND ; Load base address DAD B ; Form relative address POP PSW ; Get flags PCHL ; Jump to relative address Cond: JNZ EXEC ; whether to execute or skip it. JMP SKIP JZ EXEC JMP SKIP JNC EXEC JMP SKIP JC EXEC JMP SKIP JPO EXEC JMP SKIP JPE EXEC JMP SKIP JP EXEC JMP SKIP JM EXEC ; Condition not Met, Advance PC value to next Instruction Skip: XCHG ; HL = PC value MOV A,M ; Load instruction ANI 7 INX H ; Increment PC value JZ EPCH1 ; Jump if return INX H ; Increment PC value INX H ; Increment PC value JMP EPCH1 ; Condition Met. Execute Instruction Exec: XCHG ; HL = PC value MOV A,M ; Load instruction Exec1: ANI 6 JZ ERET ; Jump if return INX H ; Increment PC value MOV E,M ; Get address INX H MOV D,M Exec2: XCHG SHLD STACK+14 ; Store new PC value LXI SP,STACK+12 ; Load SP address for STOR CPI 2 JZ STOR2 ; jump if jump instruction LHLD STACK+12 ; Get stack address INX D ; Increment return PC value DCX H ; Decrement SP value MOV M,D ; Store return PC value in stack DCX H MOV M,E LXI SP,STACK+14 ; Load SP address for STOR JMP STOR1 ; Process Return Eret: LHLD STACK+12 ; Get stack address MOV E,M ; Get retun PC value INX H MOV D,M INX H LXI SP,STACK+16 PUSH D JMP STOR1 ; Store new PC value ; Process PCHL Epchl: LHLD STACK+16 ; Get HL value Epch1: SHLD STACK+14 ; Store new PC value LXI SP,STACK+12 ; Load SP for STOR JMP STOR2 ; Process RST Erst: MOV A,M ; Load Instruction ANI 38H ; Get RST address MOV E,A ; Put new PC value into DE MVI D,0 JMP EXEC2 ; Jump to EXEC to finish ; Process Sequential Instructions Thrb: MOV A,M ; Get first byte STA INST ; Store byte INX H Twob: MOV A,M ; Get byte STA INST+1 ; Store byte INX H Oneb: MOV A,M ; Get byte STA INST+2 ; Store byte INX H SHLD STACK+14 ; Store PC value LHLD STACK+12 ; HL = SP value LXI SP,STACK+18 POP D ; DE = program value POP B ; BC = program value POP PSW ; A and flags = program value SPHL ; SP = program value LHLD STACK+16 ; HL = program value Inst: DS 3 ; Execute instruction stored here SHLD STACK+16 ; Store HL LXI H,0 ; HL = 0 JC CARRY ; Determine state of carry flag DAD SP ; HL = program SP value JMP STOR Carry: DAD SP ; HL= program value STC ; Reset carry flag Stor: LXI SP,STACK+24 PUSH PSW ; Store A and flags PUSH B ; Store BC PUSH D ; Store DE LXI SP,STACK+14 Stor1: PUSH H ; Store SP value Stor2: LDA STACK+1 ; Load breakpoint mode indicator ANA A ; Set flags JZ DSPY ; Jump if not in breakpoint mode LHLD STACK+14 ; Load current PC value LDA STACK+2 ; Load lower byte of breakpoint address CMP L JNZ NEXT ; Jump if addresses not equal LDA STACK+3 ; Load lower byte of breakpoint address CMP H JNZ NEXT ; Jump if addresses not equal XRA A ; A = 0 STA STACK+1 ; Breakpoint address reached, return to single step mode Dspy: LXI H,STACK+23 ; Load address of registers PUSH H LXI H,ASCII ; Load address of headings MVI C,6 ; C = loop count Dspy1: MVI B,3 ; B = output character count CALL OUTPT ; Output heading XTHL ; Get register address CALL CONV ; Output register value DCX H CALL CONV ; Output register value DCX H MVI B,3 ; B = output character count MOV A,C ; Check loop count RAR JNC DSPY2 ; Jump if no CR output MVI B,4 ; Increase character count for CR Dspy2: XCHG LXI H,SPACE ; Load output address CALL OUTPT POP H ; Get heading address PUSH D ; Store register address INX H DCR C ; Decrement loop count JNZ DSPY1 ; Jump if not finished POP D ; Get rid of address POP D ; DE = SP value POP H ; HL = PC value PUSH H PUSH D PUSH D LXI D,-6 DAD D ; HL = PC - 6 MVI C,0CH ; C = loop count XCHG Dspy3: LXI H,SPACE ; HL = output address MOV A,C ; Check loop count CPI 6 JNZ DSPY4 ; Jump if no asterisk output DCX H ; Change address for asterisk Dspy4: MVI B,2 ; Load output count CALL OUTPT XCHG CALL CONV ; Output PC value INX H XCHG MVI B,3 ; Load output count LXI H,SPACE CALL OUTPT ; Output spaces POP H ; Get address of SP PUSH D ; Store address of PC CALL CONV ; Output SP value INX H CALL CONV INX H POP D ; Get PC address PUSH H ; Store address of SP MVI B,1 ; Load count for CR LXI H,SPACE+3 ; HL = address of CR CALL OUTPT ; Output CR DCR C ; Decrement loop count JNZ DSPY3 ; Continue output? CALL INP ; Wait for input CPI 'B' ; Breakpoint? JNZ CONT ; Jump if not breakpoint STA STACK+1 ; Change breakpoint indicator CALL LOC ; Get breakpoint address SHLD STACK+2 ; Store breakpoint address LXI H,SPACE+3 ; Load CR address MVI B,1 ; Load output count CALL OUTPT ; Output CR Cont: LHLD STACK+14 ; HL = PC JMP NEXT ; Register Storage Stack: DS 26 ; Reserve 26 bytes for STACK ; ASCII Headings Ascii: DW 'A ' DW '=B' DW 'C=' DW 'DE' DW '=H' DW 'L=' DW 'PC' DW '=S' DW 'P=' DB '*' Space: DB ' ' DW ' ' DW 0D0AH ; This Routine gets a Four Digit ASCII Address from an Input Device, Converts ; to Hex and Returns with Value in HL Loc: MVI B,4 ; Load loop count Loc1: CALL INP ; Get character DAD H ; Shift HL four places DAD H DAD H DAD H CPI 40H ; Convert to hex JC LOC2 ; Jump if number ADI 9 ; Add bias to letter Loc2: ANI 0FH ; Strip off upper bits ORA L MOV L,A ; Move to HL register DCR B ; Decrement loop count JNZ LOC1 RET ; This Routine Converts the Byte Pointed to by HL from Hex to ASCII and ; Outputs the two Digits Conv: MVI D,2 ; Load loop count MOV A,M ; Get byte MOV E,A ; Store in E RRC ; Shift A four times RRC RRC RRC Conv1: ANI 0FH ; Mask out upper bits CPI 0AH JC CONV2 ; Jump if number ADI 7 ; Add bias for letter Conv2: ADI 30H ; Add bias for ASCII MOV M,A ; Store character in memory INR B ; B = 1 CALL OUTPT ; Output character MOV A,E ; Move character to A DCR D ; Decrement loop count JNZ CONV1 ; Jump if not finished MOV M,E ; Restore character to memory RET ; ---------------------------------------------- ; CP/M hook ; ---------------------------------------------- BDOS EQU 0005H .CONIN EQU 1 .CONOUT EQU 2 ; ---------------------------------------------- ; This Routine Outputs a String of Characters, B = Number of Characters, HL ; Points to the Characters Outpt: PUSH D Outptl: PUSH B PUSH H MOV E,M ; Get output character MVI C,.CONOUT CALL BDOS ; Output character POP H POP B INX H ; Advance pointer DCR B ; Decrement loop count JNZ OUTPL POP D RET ; Return if done ; This Routine Inputs one Character Inp: PUSH B PUSH D PUSH H MVI C,.CONIN CALL BDOS ; Get character POP H POP D POP B RET END