📄 mon88.asm
字号:
JMP CMD ; Next Command
;----------------------------------------------------------------------
; Change Register
; Valid register names: AX,BX,CX,DX,SP,BP,SI,DI,DS,ES,SS,CS,IP,FL (flag)
;----------------------------------------------------------------------
CHANGEREG: CALL RXCHAR ; Get Command First Register character
CALL TO_UPPER
MOV DH,AL
CALL RXCHAR ; Get Second Register character, DX=register
CALL TO_UPPER
MOV DL,AL
MOV BX,OFFSET REGTAB
CMPREG: MOV AX,[BX]
CMP AX,DX ; Compare register string with user input
JNE NEXTREG ; No, continue search
WREQUAL
CALL GETHEX4 ; Get new value
MOV CX,AX ; CX=New reg value
LEA DI,UAX ; Point to User Register Storage
MOV BL,[BX+2] ; Get Offset
XOR BH,BH
MOV [DI+BX],CX
JMP DISPREG ; Display All registers
NEXTREG: ADD BX,4
CMP BX,OFFSET ENDREG
JNE CMPREG ; Continue looking
MOV SI,OFFSET ERRREG_MESS ; Display Unknown Register Name
CALL PUTS
JMP CMD ; Try Again
REGTAB DW 'AX',0 ; register name, offset
DW 'BX',2
DW 'CX',4
DW 'DX',6
DW 'SP',8
DW 'BP',10
DW 'SI',12
DW 'DI',14
DW 'DS',16
DW 'ES',18
DW 'SS',20
DW 'CS',22
DW 'IP',24
DW 'FL',26
ENDREG DW '??'
;----------------------------------------------------------------------
; Change Base Segment pointer
; Dump/Fill/Load operate on BASE_SEGMENT:[USER INPUT ADDRESS]
; Note: CB command will not update the User Registers!
;----------------------------------------------------------------------
CHANGEBS: MOV AX,ES ; WORD BASE_SEGMENT
CALL PUTHEX4 ; Display current value
WRSPACE
CALL GETHEX4
PUSH AX
POP ES
JMP CMD ; Next Command
;----------------------------------------------------------------------
; Trace Next
;----------------------------------------------------------------------
TRACENEXT: MOV AX,[UFL] ; Get User flags
OR AX,0100h ; set TF
MOV [UFL],AX
JMP TRACNENTRY
;----------------------------------------------------------------------
; Trace Program from Address
;----------------------------------------------------------------------
TRACEPROG: MOV AX,[UFL] ; Get User flags
OR AX,0100h ; set TF
MOV [UFL],AX
JMP TRACENTRY ; get execute address, save user registers etc
;----------------------------------------------------------------------
; Execute program
; 1) Enable all Breakpoints (replace opcode with INT3 CC)
; 2) Restore User registers
; 3) Jump to BASE_SEGMENT:USER_OFFSET
;----------------------------------------------------------------------
EXECPROG: MOV BX,OFFSET BPTAB ; Enable All breakpoints
MOV CX,8
NEXTENBP: MOV AX,8
SUB AL,CL
TEST BYTE [BX+3],1 ; Check enable/disable flag
JZ NEXTEXBP
MOV DI,[BX] ; Get Breakpoint Address
MOV BYTE ES:[DI],0CCh ; Write INT3 instruction to address
NEXTEXBP: ADD BX,4 ; Next entry
LOOP NEXTENBP
TRACENTRY: MOV AX,ES ; Display Segment Address
CALL PUTHEX4
MOV AL,':'
CALL TXCHAR
CALL GETHEX4 ; Get new IP
MOV [UIP],AX ; Update User IP
MOV AX,ES
MOV [UCS],AX
; Single Step Registers
; bit3 bit2 bit1 bit0
; | | | \--- '1' =Enable Single Step
; | | \-------- '1' =Select TXMON output for UARTx
; \-----\------------- '00'=No Step
; '01'=Step
; '10'=select step_sw input
; '11'=select not(step_sw) input
; MOV DX,HWM_CONFIG
; MOV AL,07h ; xxxx-0111 step=1
; OUT DX,AL ; Enable Trace
TRACNENTRY: MOV AX,[UAX] ; Restore User Registers
MOV BX,[UBX]
MOV CX,[UCX]
MOV DX,[UDX]
MOV BP,[UBP]
MOV SI,[USI]
MOV DI,[UDI]
MOV ES,[UES]
CLI ; User User Stack!!
MOV SS,[USS]
MOV SP,[USP]
PUSH [UFL]
PUSH [UCS] ; Push CS (Base Segment)
PUSH [UIP]
MOV DS,[UDS]
IRET ; Execute!
;----------------------------------------------------------------------
; Write Byte to Output port
;----------------------------------------------------------------------
OUTPORTB: CALL GETHEX4 ; Get Port address
MOV DX,AX
WREQUAL
CALL GETHEX2 ; Get Port value
OUT DX,AL
JMP CMD ; Next Command
;----------------------------------------------------------------------
; Write Word to Output port
;----------------------------------------------------------------------
OUTPORTW: CALL GETHEX4 ; Get Port address
MOV DX,AX
WREQUAL
CALL GETHEX4 ; Get Port value
OUT DX,AX
JMP CMD ; Next Command
;----------------------------------------------------------------------
; Read Byte from Input port
;----------------------------------------------------------------------
INPORTB: CALL GETHEX4 ; Get Port address
MOV DX,AX
WREQUAL
IN AL,DX
CALL PUTHEX2
JMP CMD ; Next Command
;----------------------------------------------------------------------
; Read Word from Input port
;----------------------------------------------------------------------
INPORTW: CALL GETHEX4 ; Get Port address
WREQUAL
CALL TXCHAR
IN AX,DX
CALL PUTHEX4
JMP CMD ; Next Command
;----------------------------------------------------------------------
; Display Memory
;----------------------------------------------------------------------
DUMPMEM: CALL GETRANGE ; Range from BX to DX
NEXTDMP: MOV SI,OFFSET DUMPMEMS ; Store ASCII values
CALL NEWLINE
MOV AX,ES
CALL PUTHEX4
MOV AL,':'
CALL TXCHAR
MOV AX,BX
AND AX,0FFF0h
CALL PUTHEX4
WRSPACE ; Write Space
WRSPACE ; Write Space
MOV AH,BL ; Save lsb
AND AH,0Fh ; 16 byte boundary
CALL WRNSPACE ; Write AH spaces
CALL WRNSPACE ; Write AH spaces
CALL WRNSPACE ; Write AH spaces
DISPBYTE: MOV CX,16
SUB CL,AH
LOOPDMP1: MOV AL,ES:[BX] ; Get Byte and display it in HEX
MOV DS:[SI],AL ; Save it
CALL PUTHEX2
WRSPACE ; Write Space
INC BX
INC SI
CMP BX,DX
JNC SHOWREM ; show remaining
LOOP LOOPDMP1
CALL PUTSDMP ; Display it
CMP DX,BX ; End of memory range?
JNC NEXTDMP ; No, continue with next 16 bytes
SHOWREM: MOV SI,OFFSET DUMPMEMS ; Stored ASCII values
MOV AX,BX
AND AX,0000Fh
TEST AL
JZ SKIPCLR
ADD SI,AX ; Offset
MOV AH,16
SUB AH,AL
MOV CL,AH
XOR CH,CH
MOV AL,' ' ; Clear non displayed values
NEXTCLR: MOV DS:[SI],AL ; Save it
INC SI
LOOP NEXTCLR
CALL WRNSPACE ; Write AH spaces
CALL WRNSPACE ; Write AH spaces
CALL WRNSPACE ; Write AH spaces
SKIPCLR: XOR AH,AH
CALL PUTSDMP
EXITDMP: JMP CMD ; Next Command
PUTSDMP: MOV SI,OFFSET DUMPMEMS ; Stored ASCII values
WRSPACE ; Add 2 spaces
WRSPACE
CALL WRNSPACE ; Write AH spaces
MOV CX,16
SUB CL,AH ; Adjust if not started at xxx0
NEXTCH: LODSB ; Get character AL=DS:[SI++]
CMP AL,01Fh ; 20..7E printable
JBE PRINTDOT
CMP AL,07Fh
JAE PRINTDOT
JMP PRINTCH
PRINTDOT: MOV AL,'.'
PRINTCH: CALL TXCHAR
LOOP NEXTCH ; Next Character
RET
WRNSPACE: PUSH AX ; Write AH space, skip if 0
PUSH CX
TEST AH
JZ EXITWRNP
XOR CH,CH ; Write AH spaces
MOV CL,AH
MOV AL,' '
NEXTDTX: CALL TXCHAR
LOOP NEXTDTX
EXITWRNP: POP CX
POP AX
RET
;----------------------------------------------------------------------
; Fill Memory
;----------------------------------------------------------------------
FILLMEM: CALL GETRANGE ; First get range BX to DX
WRSPACE
CALL GETHEX2
PUSH AX ; Store fill character
CALL NEWLINE
CMP DX,BX
JB EXITFILL
DOFILL: SUB DX,BX
MOV CX,DX
MOV DI,BX ; ES:[DI]
POP AX ; Restore fill char
NEXTFILL: STOSb
LOOP NEXTFILL
STOSb ; Last byte
EXITFILL: JMP CMD ; Next Command
;----------------------------------------------------------------------
; Display Registers
;
; AX=0001 BX=0002 CX=0003 DX=0004 SP=0005 BP=0006 SI=0007 DI=0008
; DS=0009 ES=000A SS=000B CS=000C IP=0100 ODIT-SZAPC=0000-00000
;----------------------------------------------------------------------
DISPREG: CALL NEWLINE
MOV SI,OFFSET REG_MESS ; OFFSET -> SI
LEA DI,UAX
MOV CX,8
NEXTDR1: CALL PUTS ; Point to first "AX=" string
MOV AX,[DI] ; DI points to AX value
CALL PUTHEX4 ; Display AX value
ADD SI,5 ; point to "BX=" string
ADD DI,2 ; Point to BX value
LOOP NEXTDR1 ; etc
CALL NEWLINE
MOV CX,5
NEXTDR2: CALL PUTS ; Point to first "DS=" string
MOV AX,[DI] ; DI points to DS value
CALL PUTHEX4 ; Display DS value
ADD SI,5 ; point to "ES=" string
ADD DI,2 ; Point to ES value
LOOP NEXTDR2 ; etc
MOV SI,OFFSET FLAG_MESS
CALL PUTS
MOV SI,OFFSET FLAG_VALID ; String indicating which bits to display
MOV BX,[DI] ; get flag value in BX
MOV CX,8 ; Display first 4 bits
NEXTBIT1: LODSB ; Get display/notdisplay flag AL=DS:[SI++]
CMP AL,'X' ; Display?
JNE SHFTCAR ; Yes, shift bit into carry and display it
SAL BX,1 ; no, ignore bit
JMP EXITDISP1
SHFTCAR: SAL BX,1
JC DISP1
MOV AL,'0'
JMP DISPBIT
DISP1: MOV AL,'1'
DISPBIT: CALL TXCHAR
EXITDISP1: LOOP NEXTBIT1
MOV AL,'-' ; Display seperator 0000-00000
CALL TXCHAR
MOV CX,8 ; Display remaining 5 bits
NEXTBIT2: LODSB ; Get display/notdisplay flag AL=DS:[SI++]
CMP AL,'X' ; Display?
JNE SHFTCAR2 ; Yes, shift bit into carry and display it
SAL BX,1 ; no, ignore bit
JMP EXITDISP2
SHFTCAR2: SAL BX,1
JC DISP2
MOV AL,'0'
JMP DISPBIT2
DISP2: MOV AL,'1'
DISPBIT2: CALL TXCHAR
EXITDISP2: LOOP NEXTBIT2
CALL NEWLINE ; Display CS:IP Instr
MOV AX,[UCS]
CALL PUTHEX4
MOV AL,':'
CALL TXCHAR
MOV AX,[UIP]
CALL PUTHEX4
WRSPACE
MOV AX,[UIP] ; Address in AX
CALL DISASM_AX ; Disassemble Instruction & Display
JMP CMD ; Next Command
REG_MESS DB "AX=",0,0 ; Display Register names table
DB " BX=",0
DB " CX=",0
DB " DX=",0
DB " SP=",0
DB " BP=",0
DB " SI=",0
DB " DI=",0
DB "DS=",0,0
DB " ES=",0
DB " SS=",0
DB " CS=",0
DB " IP=",0
;----------------------------------------------------------------------
; Load Hex, terminate when ":00000001FF" is received
; Mon88 may hang if this string is not received
; Print '.' for each valid received frame, exit upon error
; Bytes are loaded at Segment=ES
;----------------------------------------------------------------------
LOADHEX: MOV SI,OFFSET LOAD_MESS ; Display Ready to receive upload
CALL PUTS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -