📄 mon88.asm
字号:
;**********************************************************************
;
; MON88 (c) HT-LAB
;
; - Simple Monitor for 8088/86
; - Some bios calls
; - Disassembler based on David Moore's "disasm.c - x86 Disassembler v 0.1"
; - Requires roughly 14K, default segment registers set to 0380h
; - Assembled using A86 assembler
;
;----------------------------------------------------------------------
;
; Copyright (C) 2005 Hans Tiggeler - http://www.ht-lab.com
; Send comments and bugs to : cpu86@ht-lab.com
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software Foundation,
; Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;----------------------------------------------------------------------
;
; Ver 0.1 30 July 2005 H.Tiggeler WWW.HT-LAB.COM
;**********************************************************************
LF EQU 0Ah
CR EQU 0Dh
ESC EQU 01Bh
;----------------------------------------------------------------------
; UART settings, COM1
;----------------------------------------------------------------------
COM1 EQU 03F8h
COM2 EQU 02F8h
COMPORT EQU COM1 ; Select Console I/O Port
DATAREG EQU 0
STATUS EQU 1
DIVIDER EQU 2
TX_EMPTY EQU 02
RX_AVAIL EQU 01
FRAME_ERR EQU 04
;----------------------------------------------------------------------
; Used for Load Hex file command
;----------------------------------------------------------------------
EOF_REC EQU 01 ; End of file record
DATA_REC EQU 00 ; Load data record
EAD_REC EQU 02 ; Extended Address Record, use to set CS
SSA_REC EQU 03 ; Execute Address
;----------------------------------------------------------------------
; PIO Base Address
;----------------------------------------------------------------------
PIO EQU 0398h
;----------------------------------------------------------------------
; Real Time Clock
;----------------------------------------------------------------------
RTC_BASE EQU 0070h
RTC_DATA EQU 0071h
;----------------------------------------------------------------------
; Hardware Single Step Monitor, CPU86 IP Core only!
; Single Step Registers
;
; bit3 bit2 bit1 bit0 HWM_CONFIG
; | | | \--- '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
;----------------------------------------------------------------------
;HWM_CONFIG EQU 0360h
;HWM_BITLOW EQU 0362h ; 10 bits divider
;HWM_BITHIGH EQU 0363h ; bps=clk/HWM_BIT(9 downto 0)
;------------------------------------------------------------------------------------
; Default Base Segment Pointer
; All MON88 commands operate on the BASE_SEGMENT:xxxx address.
; The base_segment value can be changed by the BS command
;------------------------------------------------------------------------------------
BASE_SEGMENT EQU 0380h
WRSPACE MACRO ; Write space character
MOV AL,' '
CALL TXCHAR
#EM
WREQUAL MACRO ; Write = character
MOV AL,'='
CALL TXCHAR
#EM
ORG 0400h ; First 1024 bytes used for int vectors
INITMON: MOV AX,CS ; Cold entry point
MOV DS,AX ;
MOV SS,AX
MOV AX,OFFSET TOS ; Top of Stack
MOV SP,AX ; Set Stack pointer
;----------------------------------------------------------------------
; Set baudrate for Hardware Monitor
; 10 bits divider
; Actel Board 9.8214/38400 -> BIT_LOW=255
; 192 for 7.3864MHz
;----------------------------------------------------------------------
; MOV DX,HWM_BITLOW
; MOV AL,255 ; Set for Actel Board 9.8214
; OUT DX,AL ; 38400 bps
;
; MOV DX,HWM_BITHIGH
; MOV AL,00
; OUT DX,AL
;----------------------------------------------------------------------
; Install Interrupt Vectors
; INT1 & INT3 used for single stepping and breakpoints
; INT# * 4 = Offset
; INT# * 4 + 2 = Segment
;----------------------------------------------------------------------
XOR AX,AX ; Segment=0000
MOV ES,AX
; Point all vectors to unknown handler!
XOR BX,BX ; 256 vectors * 4 bytes
NEXTINTS: MOV WORD ES:[BX], OFFSET INTX ; Spurious Interrupt Handler
MOV WORD ES:[BX+2], 0
ADD BX,4
CMP BX,0400h
JNE NEXTINTS
MOV ES:[WORD 04], OFFSET INT1_3 ; INT1 Single Step handler
MOV ES:[WORD 12], OFFSET INT1_3 ; INT3 Breakpoint handler
MOV ES:[WORD 64], OFFSET INT10 ; INT10h
MOV ES:[WORD 88], OFFSET INT16 ; INT16h
MOV ES:[WORD 104],OFFSET INT1A ; INT1A, Timer functions
MOV ES:[WORD 132],OFFSET INT21 ; INT21h
;----------------------------------------------------------------------
; Entry point, Display welcome message
;----------------------------------------------------------------------
START: CLD
MOV SI,OFFSET WELCOME_MESS ; OFFSET -> SI
CALL PUTS ; String pointed to by DS:[SI]
MOV AX,BASE_SEGMENT ; Get Default Base segment
MOV ES,AX
;----------------------------------------------------------------------
; Process commands
;----------------------------------------------------------------------
CMD: MOV SI,OFFSET PROMPT_MESS ; Display prompt >
CALL PUTS
CALL RXCHAR ; Get Command First Byte
CALL TO_UPPER
MOV DH,AL
MOV BX,OFFSET CMDTAB1 ; Single Command?
CMPCMD1: MOV AL,[BX]
CMP AL,DH
JNE NEXTCMD1
WRSPACE
JMP [BX+2] ; Execute Command
NEXTCMD1: ADD BX,4
CMP BX,OFFSET ENDTAB1
JNE CMPCMD1 ; Continue looking
CALL RXCHAR ; Get Second Command Byte, DX=command
CALL TO_UPPER
MOV DL,AL
MOV BX,OFFSET CMDTAB2
CMPCMD2: MOV AX,[BX]
CMP AX,DX
JNE NEXTCMD2
WRSPACE
JMP [BX+2] ; Execute Command
NEXTCMD2: ADD BX,4
CMP BX,OFFSET ENDTAB2
JNE CMPCMD2 ; Continue looking
MOV SI,OFFSET ERRCMD_MESS ; Display Unknown Command, followed by usage message
CALL PUTS
JMP CMD ; Try again
CMDTAB1 DW 'L',LOADHEX ; Single char Command Jump Table
DW 'R',DISPREG
DW 'G',EXECPROG
DW 'N',TRACENEXT
DW 'T',TRACEPROG
DW 'U',DISASSEM
DW 'H',DISPHELP
DW '?',DISPHELP
DW 'Q',EXITMON
DW CR ,CMD
ENDTAB1 DW ' '
CMDTAB2 DW 'FM',FILLMEM ; Double char Command Jump Table
DW 'DM',DUMPMEM
DW 'BP',SETBREAKP ; Set Breakpoint
DW 'CB',CLRBREAKP ; Clear Breakpoint
DW 'DB',DISPBREAKP ; Display Breakpoint
DW 'CR',CHANGEREG ; Change Register
DW 'OB',OUTPORTB
DW 'BS',CHANGEBS ; Change Base Segment Address
DW 'OW',OUTPORTW
DW 'IB',INPORTB
DW 'IW',INPORTW
DW 'WB',WRMEMB ; Write Byte to Memory
DW 'WW',WRMEMW ; Write Word to Memory
ENDTAB2 DW '??'
;----------------------------------------------------------------------
; Set Breakpoint
;----------------------------------------------------------------------
SETBREAKP: MOV BX,OFFSET BPTAB ; BX point to Breakpoint table
CALL GETHEX1 ; Set Breakpoint, first get BP number
AND AL,07h ; Allow 8 breakpoints
XOR AH,AH
SHL AL,1 ; *4 to get offset
SHL AL,1
ADD BX,AX ; point to table entry
MOV BYTE [BX+3],1 ; Enable Breakpoint
WRSPACE
CALL GETHEX4 ; Get Address
MOV [BX],AX ; Save Address
MOV DI,AX
MOV AL,ES:[DI] ; Get the opcode
MOV [BX+2],AL ; Store in table
JMP DISPBREAKP ; Display Enabled Breakpoints
;----------------------------------------------------------------------
; Clear Breakpoint
;----------------------------------------------------------------------
CLRBREAKP: MOV BX,OFFSET BPTAB ; BX point to Breakpoint table
CALL GETHEX1 ; first get BP number
AND AL,07h ; Only allow 8 breakpoints
XOR AH,AH
SHL AL,1 ; *4 to get offset
SHL AL,1
ADD BX,AX ; point to table entry
MOV BYTE [BX+3],0 ; Clear Breakpoint
JMP DISPBREAKP ; Display Remaining Breakpoints
;----------------------------------------------------------------------
; Display all enabled Breakpoints
; # Addr
; 0 1234
;----------------------------------------------------------------------
DISPBREAKP: CALL NEWLINE
MOV BX,OFFSET BPTAB
MOV CX,8
NEXTCBP: MOV AX,8
SUB AL,CL
TEST BYTE [BX+3],1 ; Check enable/disable flag
JZ NEXTDBP
CALL PUTHEX1 ; Display Breakpoint Number
WRSPACE
MOV AX,[BX] ; Get Address
CALL PUTHEX4 ; Display it
WRSPACE
MOV AX,[BX] ; Get Address
CALL DISASM_AX ; Disassemble instruction & Display it
CALL NEWLINE
NEXTDBP: ADD BX,4 ; Next entry
LOOP NEXTCBP
JMP CMD ; Next Command
;----------------------------------------------------------------------
; Breakpoint Table, Address(2), Opcode(1), flag(1) enable=1, disable=0
;----------------------------------------------------------------------
BPTAB DB 4 DUP 0
DB 4 DUP 0
DB 4 DUP 0
DB 4 DUP 0
DB 4 DUP 0
DB 4 DUP 0
DB 4 DUP 0
DB 4 DUP 0
;----------------------------------------------------------------------
; Disassemble Range
;----------------------------------------------------------------------
DISASSEM: CALL GETRANGE ; Range from BX to DX
CALL NEWLINE
LOOPDIS1: PUSH DX
MOV AX,BX ; Address in AX
CALL PUTHEX4 ; Display it
LEA BX,DISASM_CODE ; Pointer to code storage
LEA DX,DISASM_INST ; Pointer to instr string
CALL disasm_ ; Disassemble Opcode
MOV BX,AX ;
PUSH AX ; New address returned in AX
WRSPACE
MOV SI,offset DISASM_CODE
CALL PUTS
CALL STRLEN ; String in SI, Length in AL
MOV AH,15
SUB AH,AL
CALL WRNSPACE ; Write AH spaces
MOV SI,offset DISASM_INST
CALL PUTS
CALL NEWLINE
POP AX
POP DX
CMP DX,BX
JNB LOOPDIS1
EXITDIS: JMP CMD ; Next Command
;----------------------------------------------------------------------
; Disassemble Instruction at AX and Display it
; Return updated address in AX
;----------------------------------------------------------------------
DISASM_AX: PUSH ES ; Disassemble Instruction
PUSH SI
PUSH DX
PUSH BX
PUSH AX
MOV AX,[UCS] ; Get Code Base segment
MOV ES,AX ;
LEA BX,DISASM_CODE ; Pointer to code storage
LEA DX,DISASM_INST ; Pointer to instr string
POP AX ; Address in AX
CALL disasm_ ; Disassemble Opcode
MOV SI,offset DISASM_CODE
CALL PUTS
CALL STRLEN ; String in SI, Length in AL
MOV AH,15
SUB AH,AL
CALL WRNSPACE ; Write AH spaces
MOV SI,offset DISASM_INST
CALL PUTS
POP BX
POP DX
POP SI
POP ES
RET
;----------------------------------------------------------------------
; Write Byte to Memory
;----------------------------------------------------------------------
WRMEMB: CALL GETHEX4 ; Get Address
MOV BX,AX ; Store Address
WRSPACE
MOV AL,ES:[BX] ; Get current value and display it
CALL PUTHEX2
WREQUAL
CALL GETHEX2 ; Get new value
MOV ES:[BX],AL ; and write it
JMP CMD ; Next Command
;----------------------------------------------------------------------
; Write Word to Memory
;----------------------------------------------------------------------
WRMEMW: CALL GETHEX4 ; Get Address
MOV BX,AX
WRSPACE
MOV AX,ES:[BX] ; Get current value and display it
CALL PUTHEX4
WREQUAL
CALL GETHEX4 ; Get new value
MOV ES:[BX],AX ; and write it
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -