title MORROW 80188 Slave Debugger
page 62, 132
.list
;****************************************************************************
;
; MBUG
;
; MORROW 80188 debugger.
;
; This debugger is written for the MORROW 80188 slave board. The
; debugger will use the serial port attached to the I/O connector
; as the console port. The commands are single letter commands
; and behave as they are described below. Where possible, the
; syntax is kept as close to the 'debug' utility syntax under MSDOS.
; The commands currently supported are:
;
; d - dumps memory in hexadecimal and ascii.
; e - allows modification of memory one byte at a time.
; f - fill memory block with value.
; i - displays value at input port.
; m - move block of memory.
; o - output byte value to output port.
; j - start executing at address.
;
; The debugger is intended to be burned into ROM. For debugging
; purposes, the code was first written to run under MSDOS 2.0.
; The hardware drivers are then replaced with the ones for the
; slave card before burning into ROM. This version of code
; contains the hardware drivers for the Morrow slave card.
;
; The debugger is contained in 2 files. They are MBUG.ASM and
; MFUNCT.ASM. MBUG.ASM contains the main scanner and parser of
; commands and MFUNCT.ASM contains the code for the specific
; functions of the debugger.
;
; The debugger should be assembled and linked as follows for the
; MSDOS version:
; masm mbug; * this generates MBUG.OBJ
; link mbug; * this produces MBUG.EXE
;
; The file MBUG.EXE can then be run under MSDOS for testing.
;
;
; MODIFICATIONS:
;
; 5/7/84 written Raymond Yu
; 5/15/84 V1.0 completed RYU
; tested under MSDOS 2.0
; 6/4/84 revised for ROM RYU
; renamed 'mbugrom.asm'
; 'mfunct.asm' remains
;
;****************************************************************************
data segment para public 'data'
;**********************************************************************
;
; S100 80188 slave board constant and address definitions
;
;**********************************************************************
; 80188 internal control registers
cntrl_base equ 0ff00h ; base addr of 80188 control ports
; in I/O space, this is the default
; addr immediately after a reset
umcs equ cntrl_base+0a0h ; addr of upper memory select reg
lmcs equ cntrl_base+0a2h ; addr of lower memory select reg
mpcs equ cntrl_base+0a8h ; addr of middle memory select reg
mmcs equ cntrl_base+0a6h ; addr of middle memory select reg
pacs equ cntrl_base+0a4h ; addr of peripheral select reg
; 80188 control register initialization values
UMCSVAL equ 0ff38h ; 4K byte block, 0 wait states,
; use external ready
LMCSVAL equ 03ff8h ; 256K byte block, 0 wait states,
; use external ready
MPCSVAL equ 0a0bfh ; 256K byte block in 64K byte incr,
; 7 PCS lines mapped into I/O space
MMCSVAL equ 041f8h ; middle ram starts at 256K,
; 0 wait states, use external ready
PACSVAL equ 0003fh ; PCS decoding starts at 0 in
; I/O space, 3 wait states,
; ignore external ready
;********** 8250 UART constant and address definitions ****************
uart_base equ 0 ; addr of uart in I/O space
; UART registers
uartdata equ uart_base+0 ; data register for uart .. DLAB=0
uartdivisorlow equ uart_base+0 ; clk divisor, low byte .. DLAB=1
uartdivisorhi equ uart_base+1 ; clk divisor, high byte .. DLAB=1
uartinten equ uart_base+1 ; interrupt enable register .. DLAB=0
uartintident equ uart_base+2 ; interrupt identification (read only)
uartlinecntrl equ uart_base+3 ; line control register
uartmdmcntrl equ uart_base+4 ; modem control register
uartlinestatus equ uart_base+5 ; line status register
uartmdmstatus equ uart_base+6 ; modem status register
; UART register bit definitions
; interrupt enable register
rcvinten equ 01h ; enable data received interrupt bit
xmitinten equ 02h ; enable transmitter buffer empty int
rcvlineinten equ 04h ; enable receiver line status int bit
mdmstatinten equ 010h ; enable modem status interrupt bit
; interrupt identification register (read only)
intpending equ 01h ; interrupt pending bit mask
intid equ 06h ; interrupt ID mask ( 2 bits )
; line control register
setbreak equ 040h ; set break bit
dlab equ 080h ; divisor latch access enable bit
; modem control register
dtr equ 01h ; data terminal ready bit
rts equ 02h ; request to send bit
out1 equ 04h ; output bit 1
out2 equ 08h ; output bit 2
loopcntrl equ 010h ; loop control bit
; line status register
dataready equ 01h ; data ready status bit
overrunerr equ 02h ; overrun error status bit
parityerr equ 04h ; parity error status bit
framingerr equ 08h ; framing error status bit
breakint equ 010h ; break interrupt status bit
thre equ 020h ; transmitter holding register empty
tsre equ 040h ; transmitter shift register empty
; modem status register
dcts equ 01h ; delta clear to send status bit
ddsr equ 02h ; delta data set ready status bit
teri equ 04h ; trailing edge ring indicator status
drlsd equ 08h ; delta rcv line signal detect status
cts equ 010h ; clear to send status read bit
dsr equ 020h ; data set ready status read bit
ri equ 040h ; ring indicator status read bit
rlsd equ 080h ; rcv line signal detect status bit
; initialization values for divisor latch
; divisor values for baud rates using 1.8432Mhz 16X clock
baud9600 equ 12
baud4800 equ 24
baud2400 equ 48
baud1200 equ 96
baud300 equ 384
; initialization values for line control register and
; modem control register
LCRVAL equ 07h ; 8 data bits, 2 stop bits, no parity
MCRVAL equ 0fh ; DTR, RTS, OUT1, OUT2 set
;******************************************************************
;
; Debugger constant and string definitions
;
;******************************************************************
PRSTRING equ 09h ; DOS print string function
ENDSTRING equ '$' ; string termination char
CR equ 0dh ; carriage return char
LF equ 0ah ; line feed char
BS equ 08h ; backspace char
DELETE equ 07fh ; delete char
KILL equ 018h ; control-x is kill char
SPACE equ 020h ; space char
BUFLENGTH equ 128 ; size of command buffer
SRC_SEG equ 0 ; init source segment value
DEST_SEG equ 0 ; init dest segment value
DEF_COUNT equ 128 ; default count of bytes
SIGNON db CR,LF
db "MORROW DESIGNS 80188 DEBUGGER V1.0 5/7/84"
db CR,LF,CR,LF,ENDSTRING
NEWLINE db CR,LF,ENDSTRING
PROMPT db "MBUG>",ENDSTRING
BAD_COMMAND db "COMMAND NOT FOUND",ENDSTRING
SYNTAX_MES db "usage: ",ENDSTRING
SPACE_2 db " ",ENDSTRING
SPACE_3 db " ",ENDSTRING
SPACE_4 db " ",ENDSTRING
DENTRY db " = ",ENDSTRING
syntax label byte
S_DUMP db "d
"
db CR,LF,ENDSTRING
S_ENTER db "e ",CR,LF,ENDSTRING
S_FILL db "f "
db CR,LF,ENDSTRING
S_INPUT db "i ",CR,LF,ENDSTRING
S_MOVE db "m "
db CR,LF,ENDSTRING
S_OUTPUT db "o ",CR,LF,ENDSTRING
S_JUMP db "j ",CR,LF,ENDSTRING
db 0 ; mark end of syntax strings
commands label byte ; command table for debugger
db 'D'
dw offset dump
db 'E'
dw offset enter
db 'F'
dw offset fill
db 'I'
dw offset input
db 'M'
dw offset move
db 'O'
dw offset output
db 'J'
dw offset jump
db 'Q'
dw offset quit
dw 0
segstore label word ; segment value temp storage
; these are used as default
dw SRC_SEG ; source segment value
dw DEST_SEG ; destination segment value
current_src dw 0 ; source address
current_dest dw 0 ; destination address
current_count dw 40h ; current count
current_port dw 0 ; current i/o port
buffer db BUFLENGTH dup(?) ; command buffer
data_buf db 0 ; count of bytes in data buf
db 8 dup(0) ; can fill memory with up to
; 8 byte sequence
end_data_seg label byte ; mark end of data segment
data ends
;**************************************************************
; CODE STARTS HERE
;**************************************************************
code segment para public 'code'
assume cs:code, ds:data, es:data
begin proc far
; initialize 80188 internal registers
mov dx,umcs ; init upper memory chip select
mov ax,UMCSVAL ; init value
out dx,ax ; output to 80188 control port
mov dx,lmcs ; init lower memory chip select
mov ax,LMCSVAL ; init value
out dx,ax ; output to 80188 control port
mov dx,mmcs ; init middle memory chip select
mov ax,MMCSVAL ; init value
out dx,ax ; output to 80188 control port
mov dx,mpcs ; init middle memory chip select
mov ax,MPCSVAL ; init value
out dx,ax ; output to 80188 control port
mov dx,pacs ; init peripheral chip select
mov ax,PACSVAL ; init value
out dx,ax ; output to 80188 control port
; copy initialized data out of ROM and into RAM
mov ax,40h ; data starts after interrupt vectors
mov es,ax ; put segment addr into ds reg
mov ax,data ; get address of init data in ROM
mov ds,ax ; use as source address
mov cx,offset end_data_seg
xor si,si ; clear pointers
mov di,si
rep movsb ; copy cx count bytes to RAM
mov ax,es ; put new data segment reg addr
mov ds,ax ; into ds reg
mov ax,offset end_data_seg
mov cl,4 ; divide addr by 16 to get segment
shr ax,cl
inc ax ; point at next paragraph after data
add ax,40h ; data seg starts at 400h
mov ss,ax ; use as stack pointer
mov ax,100h ; give 256 bytes to the stack
mov sp,ax
mov ax,0ffffh ; push reset address in case of
push ax ; return from main loop
xor ax,ax ; offset of reset location
push ax
; init the console uart
mov dx,uartlinecntrl
mov al,LCRVAL+dlab ; set DLAB=1 to load divisor
out dx,al
mov dx,uartdivisorlow
mov ax,baud9600 ; init port to 9600 baud
out dx,al ; output low byte of divisor
mov dx,uartdivisorhi
mov al,ah ; get high byte of divisor
out dx,al ; output high byte of divisor
mov dx,uartlinecntrl
mov al,LCRVAL ; init line control register
out dx,al
mov dx,uartmdmcntrl
mov al,MCRVAL ; init modem control register
out dx,al
; end of initialization code
mov dx,offset SIGNON
call prstr ; print sign on message
main: ; this is the main loop of
; the debugger
mov dx,offset PROMPT ; print the debugger prompt
call prstr
mov ah,0 ; convert data to upper case
call get_command ; get command line into buffer
mov al,buffer ; get first char in buffer
test al,al ; if zero then no chars entered
je main ; get the next command
call execute ; execute the command
jc main ; routine sets carry to cont
; terminate execution
ret
begin endp far
;**************************************************************
; COMMAND ENTRY AND PARSE ROUTINES
;**************************************************************
;
; get_command
;
; Get a command line into command buffer.
;
; on entry:
; ah contains 0 if the data should be converted to upper case.
; if ah is not zero then the data is entered as is.
; on return:
; command line is stored at buffer.
; usage:
; call get_command
;
get_command proc near ; get command in buffer
push ax ; save ax
; clear the buffer
mov di,offset buffer ; point to beginning of buffer
mov cx,BUFLENGTH ; length of command buffer
push es ; need to use es register
mov ax,ds ; get segment register
mov es,ax ; put in default seg reg
xor ax,ax ; fill buffer with zeroes
cld ; set dir flag to auto incr
rep stosb
pop es ; restore segment register
xor bx,bx ; clear buffer pointer
pop cx ; get param value into cx
gc_nextchar:
call getc ; get the next input char
cmp al,BS ; if backspace char
je gc_delete ; then process
cmp al,DELETE ; if delete char
je gc_delete ; then process
cmp al,KILL ; if kill char
je gc_kill ; delete entire buffer
cmp al,CR ; if CR then done
je gc_done
cmp al,SPACE ; reject other control chars
jl gc_nextchar
call putc ; echo char to display
test ch,ch ; if param is 0 then convert
jne gc_1 ; do not convert to UC
cmp al,60h ; if lower case char then
jl gc_1 ; else do nothing
and al,0dfh ; convert to upper case
gc_1:
mov buffer[bx],al ; store char away
inc bx ; point to next char in buffer
cmp bx,BUFLENGTH ; if too many chars
jg gc_err ; error exit
jmp gc_nextchar
gc_kill:
mov al,SPACE ; erase to beginning of line
call putc
mov al,BS ; back up to orig position
call putc
test bx,bx ; only to beginning of line
jz get_command
dec bx
mov al,BS ; back up one char
call putc
jmp gc_kill
gc_delete: ; delete the previous char
test bx,bx ; if at beg of buffer
jz gc_nextchar ; do nothing ... otherwise
mov al,BS ; back space to prev char
call putc
mov al,SPACE ; erase char
call putc
mov al,BS ; fix cursor
call putc
dec bx ; point at prev char position
xor al,al ; clear char in buffer
mov buffer[bx],al
jmp gc_nextchar ; get next char
gc_done:
mov dx,offset NEWLINE ; print CR, LF
call prstr
gc_err:
ret
get_command endp near
;
; execute
;
; Executes the command line contained in 'buffer'.
;
; on entry:
; the command line is assumed to be in buffer.
; the command table is at 'commands'.
; on exit:
; the carry flag is cleared if the debugger is to terminate.
; usage:
; call execute
;
execute proc near ; determine command
mov al,buffer ; get 1st char of command line
mov bx,offset commands ; point to command table
exe_search:
mov ah,[bx] ; get command in table
test ah,ah ; if zero then reached end of
je exe_bad ; table .. bad command
cmp al,ah ; if command is found ..
je exe_command ; then execute it
add bx,3 ; else skip to next command
jmp exe_search
exe_command:
inc bx ; point to addr of routine
call word ptr [bx] ; near call to routine
ret
exe_bad: ; bad command .. print error
mov dx,offset BAD_COMMAND ; message
call prstr
stc
ret
execute endp near
;**************************************************************
; DEBUGGER FUNCTIONS
;**************************************************************
include mfunct.asm
;**************************************************************
; HARDWARE RELATED ROUTINES
;**************************************************************
getc proc near ; get a char from console port
; return in al
push dx ; save dx register
mov dx,uartlinestatus
getc_wrdy:
in al,dx ; get uart status
and al,dataready ; if no char received in uart
je getc_wrdy ; wait ..
mov dx,uartdata ; get data from uart
in al,dx
and al,07fh ; get rid of ms bit
pop dx ; restore dx
ret
getc endp near
putc proc near ; write a char to console port
; char is in al reg
push dx ; save dx register
push ax ; save ax register also
mov dx,uartlinestatus
putc_wrdy:
in al,dx
and al,thre ; test if xmit holding reg empty
je putc_wrdy ; if not empty then again
pop ax ; restore ax register and char
mov dx,uartdata ; otherwise send data to port
out dx,al ; write char to uart
pop dx
ret
putc endp near
prstr proc near ; dx pts to string terminated
; by a '$'
push bx ; save bx register
push ax ; save ax register
mov bx,dx ; get string addr
prstr1:
mov al,[bx] ; get next char in string
cmp al,'$' ; see if end of string
je prstr_done ; done if so
call putc ; else send char to console
inc bx ; point at next char
jmp prstr1 ; print next char
prstr_done:
pop ax ; restore ax register
pop bx ; restore bx register
ret
prstr endp near
code ends
end