mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 08:54:17 +00:00
2553 lines
53 KiB
Plaintext
2553 lines
53 KiB
Plaintext
title 'DDT86 1.1 10/2/81'
|
||
;
|
||
; modified 5/14/81 R. Silberstein
|
||
; modified 6/15/81 R. Silberstein
|
||
; modified 8/12/81 R. Silberstein
|
||
; modified 9/6/81 R. Silberstein
|
||
; modified 9/16/81 R. Silberstein
|
||
; modified 10/1/81 R. Silberstein
|
||
;
|
||
;
|
||
; *****************************************
|
||
; * *
|
||
; * D D T 8 0 8 6 - 8 0 8 8 *
|
||
; * *
|
||
; *****************************************
|
||
;
|
||
debug equ 00h ;if set, use direct bios calls for console io
|
||
;
|
||
ddt_org equ 100h ;origin of this module
|
||
lasmorg equ ddt_org+1300h ;origin of disassembler
|
||
asmorg equ ddt_org+2200h ;origin of assembler
|
||
;
|
||
cseg
|
||
;
|
||
org 005ch
|
||
fcb rb 10h
|
||
fcb2 rb 14h
|
||
buff rb 80h
|
||
;
|
||
org lasmorg
|
||
disem: mov ax,0
|
||
ret 4 ;remove parameters from stack
|
||
;
|
||
org asmorg
|
||
assem: mov ax,0
|
||
ret 4 ;remove parameters from stack
|
||
;
|
||
org ddt_org
|
||
|
||
jmp ddt86 ;ccp transfers control here
|
||
jmp conin
|
||
jmp plmconout
|
||
jmp plmgetline
|
||
jmp asment ;get here on error in assem (pl/m)
|
||
jmp plmset ;assembler link to ddt set/verify
|
||
;
|
||
bdosint: int bdosi ;this is only here for user to patch
|
||
;actual bdos link gets set from here
|
||
bdosintloc equ offset bdosint
|
||
bdosintnum equ offset bdosint+1
|
||
;
|
||
bdosi equ 224 ;bdos interrupt number
|
||
stsize equ 96 ;stack size
|
||
nbps equ 2 ;number of breakpoints
|
||
;
|
||
ifmask16 equ 0200h ;16-bit IF mask
|
||
ifmask8 equ 02h ;8-bit IF mask
|
||
;
|
||
lf equ 0ah ;line feed
|
||
cr equ 0dh ;carriage return
|
||
eol equ cr
|
||
ctls equ 13h ;ascii ctl-s
|
||
;
|
||
; *******************************************
|
||
; * *
|
||
; * m e s s a g e s *
|
||
; * *
|
||
; *******************************************
|
||
;
|
||
copyright db ' COPYRIGHT (C) 1981, DIGITAL RESEARCH '
|
||
;
|
||
signon db 'DDT86 1.','1' or 80h
|
||
;
|
||
DATE DB ' 10/02/81 '
|
||
regname db 'A','X' or 80h
|
||
db 'B','X' or 80h
|
||
db 'C','X' or 80h
|
||
db 'D','X' or 80h
|
||
db 'S','P' or 80h
|
||
db 'B','P' or 80h
|
||
db 'S','I' or 80h
|
||
db 'D','I' or 80h
|
||
segreg db 'C','S' or 80h
|
||
db 'D','S' or 80h
|
||
db 'S','S' or 80h
|
||
db 'E','S' or 80h
|
||
db 'I','P' or 80h
|
||
;
|
||
flagname db 'ODITSZAPC'
|
||
flagbits db 5,6,7,8,9,10,12,14,16
|
||
;
|
||
segnames db 'C','S' or 80h
|
||
db 'D','S' or 80h
|
||
db 'E','S' or 80h
|
||
db 'S','S' or 80h
|
||
db 'X','1' or 80h
|
||
db 'X','2' or 80h
|
||
db 'X','3' or 80h
|
||
db 'X','4' or 80h
|
||
;
|
||
closem db cr,lf,'CANNOT CLOS','E' or 80h
|
||
loadm db cr,lf,'INSUFFICIENT MEMOR','Y' or 80h
|
||
makem db cr,lf,'NO SPAC','E' or 80h
|
||
memm db cr,lf,'MEMORY REQUEST DENIE','D' or 80h
|
||
openm db cr,lf,'NO FIL','E' or 80h
|
||
readm db ' START EN','D' or 80h
|
||
verm db cr,lf,'VERIFY ERROR AT',' ' or 80h
|
||
writem db cr,lf,'DISK WRITE ERRO','R' or 80h
|
||
;
|
||
; ****************************************************
|
||
; * *
|
||
; * i n i t i a l i z a t i o n *
|
||
; * *
|
||
; ****************************************************
|
||
;
|
||
setbdosint: ;copy vector at 0:bdosi*4 to (bdosi+1)*4
|
||
mov al,byte ptr .bdosintnum ;get bdos interrupt #
|
||
inc al
|
||
mov byte ptr .ddtbdosintnum,al ;ddt uses the next interrupt internally
|
||
sub ah,ah
|
||
shl ax,1
|
||
shl ax,1 ;bdos int # * 4
|
||
mov di,ax ;[di] points to new bdos interrupt vector
|
||
mov si,ax
|
||
sub si,4 ;[si] points to actual bdos interrupt vector
|
||
push ds ;save ds
|
||
sub ax,ax
|
||
mov es,ax ;set es and ds to 0 to move interrupt vectors
|
||
mov ds,ax
|
||
mov cx,4
|
||
rep movs al,al ;copy bdos interrupt vector to next int vector
|
||
pop ds ;restore ds
|
||
ret
|
||
;
|
||
checkcmdtail: ;if command tail not empty, assume E command
|
||
mov si,offset buff
|
||
mov ah,0
|
||
lods al ;get count from command tail
|
||
or al,al
|
||
jz cctret ;nothing to do if tail empty
|
||
cmp al,conbuffmax
|
||
jbe movcom
|
||
mov al,conbuffmax ;truncate, if needed
|
||
movcom:
|
||
mov cx,ax ;count to [cx]
|
||
mov di,offset conbuff
|
||
push ds
|
||
pop es ;point destination to ddt seg
|
||
rep movs al,al ;copy command tail into ddt command buff
|
||
mov al,eol
|
||
stos al ;store terminator
|
||
call execute ;command tail is assumed E command
|
||
cctret:
|
||
ret
|
||
;
|
||
ddt86:
|
||
cld
|
||
MOV CCPSS,SS
|
||
MOV CCPSP,SP ;SAVE CCP STACK POINTER
|
||
MOV USERSS,SS
|
||
MOV USERSP,SP ;INITIALIZE USER'S MACHINE STATE TO CCP STACK
|
||
;
|
||
pushf
|
||
pop ax ;get flags
|
||
and ax,ifmask16 ;mask to IF bit
|
||
mov sysif,ah ;save system IF state
|
||
mov userfl,ax ;initialize user's flags to sysif
|
||
;
|
||
mov ax,cs
|
||
cli ;entering critical region
|
||
mov ss,ax ;set ss = cs
|
||
mov sp,offset stackp ;set up stack pointer
|
||
test sysif,ifmask8 ;see if interrupts were enabled
|
||
jz d0 ;don't turn them on if they were off
|
||
sti
|
||
d0: ;exiting critical region
|
||
;
|
||
call setbdosint ;copy vector since ddt uses bdosi+1 internally
|
||
;
|
||
test savevecflag,0ffh ;ddt interrupts saved on each g/t/u?
|
||
jnz d1 ;if so, don't initialize here
|
||
call bpvect ;if not, initialize them here
|
||
d1:
|
||
if debug
|
||
;
|
||
sub ax,ax
|
||
mov es,ax
|
||
mov si,bdosi * 4 + 2
|
||
mov ax,es:[si] ;get bdos segment
|
||
mov es,ax
|
||
mov biosentryseg,ax
|
||
mov di,biosentryoff
|
||
mov al,81h
|
||
stos al
|
||
mov al,0c3h
|
||
stos al
|
||
mov al,0h
|
||
stos al
|
||
mov al,25h
|
||
stos al
|
||
mov al,0ffh
|
||
stos al
|
||
mov al,0d3h
|
||
stos al
|
||
mov al,0cbh
|
||
stos al
|
||
;
|
||
endif
|
||
;
|
||
mov si,offset signon ;get sign on message
|
||
call printm ;and print it
|
||
;
|
||
CALL VERSION
|
||
CMP AL,30H ;SEE IF WE ARE UNDER FILE SYSTEM III (MP/M)
|
||
MOV BH,0
|
||
JC D2 ;IF EARLIER VERSION, SKIP
|
||
MOV DL,0FEH
|
||
CALL SETERRMODE ;SO BDOS RETURNS TO DDT ON FILE ERRORS
|
||
MOV BH,1
|
||
D2:
|
||
MOV ERRMODE,BH
|
||
;
|
||
call checkcmdtail ;if non-blank, do E command
|
||
;
|
||
; *************************************************
|
||
; * *
|
||
; * w o r k i n g l o o p *
|
||
; * *
|
||
; *************************************************
|
||
;
|
||
start: cld ;direction flag points up
|
||
mov sp,offset stackp ;make sure stack is right
|
||
call crlf ;print crlf
|
||
mov al,'-' ;and prompt
|
||
call conout
|
||
call getline ;get command line
|
||
call conin ;read first char
|
||
cmp al,eol
|
||
jz start
|
||
CMP AL,';'
|
||
JZ START ;IGNORE COMMENT LINES
|
||
sub al,'A' ;check range for valid command
|
||
jb err
|
||
cmp al,'Z'-'A'
|
||
ja err
|
||
shl al,1 ;* 2 (2 bytes per ctable entry)
|
||
mov ah,0
|
||
xchg ax,bx
|
||
mov numreq,1 ;most commands require an argument
|
||
mov wmode,0 ;most commands are not word mode
|
||
call word ptr ctable [bx] ;immed call command routine
|
||
jmps start ;start over
|
||
;
|
||
err:
|
||
call crlf
|
||
mov al,'?' ;error handler
|
||
call conout ;print error char
|
||
jmps start ;stack maybe messed up, keep this jmp
|
||
;
|
||
; **************************************************
|
||
; * *
|
||
; * c o m m a n d j u m p t a b l e *
|
||
; * *
|
||
; **************************************************
|
||
;
|
||
ctable dw assm ;assemble mnemonics
|
||
DW BLOCKCOMPARE ;COMPARE MEMORY BLOCKS
|
||
dw err
|
||
dw display ;display memory
|
||
dw execute ;load user program for execution
|
||
dw fill ;fill memory with constant
|
||
dw gouser ;go to user program
|
||
dw hexmath ;compute hex sum and difference
|
||
dw ifcb ;input file control block
|
||
dw err
|
||
dw err
|
||
dw lassm ;disassemble memory
|
||
dw move ;move block
|
||
dw err
|
||
dw err
|
||
dw err
|
||
dw err
|
||
dw read ;read file
|
||
dw setmem ;set memory
|
||
dw trace ;trace program execution
|
||
dw untrace ;untraced program execution
|
||
dw verify ;display file info
|
||
dw write ;write memory block to disk
|
||
dw xcom ;display/alter CPU state
|
||
dw err
|
||
dw err
|
||
;
|
||
; *************************************************
|
||
; * *
|
||
; * b d o s i n t e r f a c e *
|
||
; * *
|
||
; *************************************************
|
||
;
|
||
bdos: ;this interrupt instruction is overwritten on initialization
|
||
;the actual int # used is the one at bdosint: + 1
|
||
ddtbdosintnum equ offset bdos + 1
|
||
;
|
||
int bdosi
|
||
ret
|
||
;
|
||
if debug
|
||
;
|
||
bios:
|
||
callf dword ptr biosentryoff
|
||
ret
|
||
;
|
||
endif
|
||
;
|
||
if debug
|
||
;
|
||
consin:
|
||
mov bx,9
|
||
call bios
|
||
push ax
|
||
call conout
|
||
pop ax
|
||
ret
|
||
;
|
||
endif
|
||
;
|
||
if not debug
|
||
;
|
||
consin:
|
||
mov cl,1
|
||
call bdos
|
||
ret
|
||
;
|
||
endif
|
||
;
|
||
if debug
|
||
;
|
||
conout:
|
||
mov bx,0ch
|
||
mov cl,al
|
||
jmp bios
|
||
;
|
||
endif
|
||
;
|
||
if not debug
|
||
;
|
||
conout:
|
||
mov cl,2
|
||
mov dl,al
|
||
call bdos
|
||
ret
|
||
;
|
||
endif
|
||
;
|
||
rdconbuff:
|
||
mov cl,10
|
||
call bdos
|
||
ret
|
||
;
|
||
if debug
|
||
;
|
||
constat:
|
||
mov bx,6
|
||
jmp bios
|
||
;
|
||
endif
|
||
;
|
||
if not debug
|
||
;
|
||
constat:
|
||
mov cl,11
|
||
call bdos
|
||
ret
|
||
;
|
||
endif
|
||
;
|
||
VERSION:
|
||
MOV CL,12
|
||
JMP BDOS
|
||
;
|
||
open:
|
||
mov cl,15
|
||
call bdos
|
||
inc al ;test for 0ffh returned
|
||
jz openerr
|
||
ret
|
||
openerr:
|
||
mov si,offset openm
|
||
jmps errm
|
||
;
|
||
close:
|
||
mov cl,16
|
||
call bdos
|
||
inc al
|
||
jz closeerr
|
||
ret
|
||
closeerr:
|
||
mov si,offset closem
|
||
jmps errm
|
||
;
|
||
delete:
|
||
mov cl,19
|
||
jmp bdos
|
||
;
|
||
readsec:
|
||
mov cl,20
|
||
jmp bdos
|
||
;
|
||
writesec:
|
||
mov cl,21
|
||
call bdos
|
||
or al,al
|
||
jnz writeerr
|
||
ret
|
||
writeerr:
|
||
mov si,offset writem
|
||
jmps errm
|
||
;
|
||
make:
|
||
mov cl,22
|
||
call bdos
|
||
inc al
|
||
jz makeerr
|
||
ret
|
||
makeerr:
|
||
mov si,offset makem
|
||
jmps errm
|
||
;
|
||
setdma:
|
||
mov cl,26
|
||
jmp bdos
|
||
;
|
||
SETERRMODE:
|
||
MOV CL,45
|
||
JMP BDOS
|
||
;
|
||
setdmab:
|
||
mov cl,51
|
||
jmp bdos
|
||
;
|
||
getmaxmem:
|
||
mov cl,53
|
||
call bdos
|
||
inc al
|
||
jz memerr
|
||
ret
|
||
;
|
||
allocabsmem:
|
||
mov cl,56
|
||
call bdos
|
||
; inc al
|
||
; jz memerr
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP ;REPLACE INC AL, JZ MEMERR
|
||
ret
|
||
memerr:
|
||
mov si,offset memm
|
||
jmps errm
|
||
;
|
||
freemem:
|
||
mov cl,57
|
||
jmp bdos
|
||
;
|
||
load:
|
||
mov cl,59
|
||
call bdos
|
||
inc ax ;test for 0ffffh returned
|
||
jz loaderr
|
||
ret
|
||
loaderr:
|
||
mov si,offset loadm
|
||
;
|
||
errm:
|
||
call printm
|
||
jmp start
|
||
;
|
||
plmconout:
|
||
push bp
|
||
mov bp,sp
|
||
mov ax,4[bp]
|
||
call conout
|
||
pop bp
|
||
ret 2
|
||
;
|
||
plmgetline:
|
||
push bp
|
||
call getline
|
||
pop bp ;restore bp for pl/m
|
||
ret
|
||
;
|
||
; ****************************************************
|
||
; * *
|
||
; * c o n s o l e i / o r o u t i n e s *
|
||
; * *
|
||
; ****************************************************
|
||
;
|
||
if debug
|
||
;
|
||
ctlx:
|
||
mov al,'#'
|
||
call conout
|
||
call crlf
|
||
getline:
|
||
mov conptr,0
|
||
get0:
|
||
call consin
|
||
cmp al,3
|
||
jz ctlc
|
||
cmp al,8
|
||
jz backsp
|
||
cmp al,24 ;ctl-x
|
||
jz ctlx
|
||
cmp al,cr
|
||
jz getlinedone
|
||
cmp conptr,conbuffmax
|
||
jnb getlinedone
|
||
mov di,offset conbuff ;normal character store
|
||
add di,conptr
|
||
mov [di],al
|
||
inc conptr
|
||
jmps get0
|
||
getlinedone:
|
||
mov di,offset conbuff
|
||
add di,conptr
|
||
mov byte ptr [di],eol
|
||
mov conptr,0
|
||
ret
|
||
backsp:
|
||
cmp conptr,0
|
||
jz get0
|
||
dec conptr
|
||
call blank
|
||
mov al,8
|
||
call conout
|
||
jmps get0
|
||
ctlc:
|
||
mov cl,0
|
||
mov dl,0
|
||
jmp bdos
|
||
;
|
||
endif
|
||
;
|
||
if not debug
|
||
;
|
||
getline:
|
||
mov dx,offset conbuffhdr
|
||
call rdconbuff
|
||
mov bl,conbuffcnt
|
||
mov bh,0
|
||
add bx,offset conbuff
|
||
mov byte ptr [bx], eol
|
||
mov conptr,0
|
||
ret
|
||
;
|
||
endif
|
||
;
|
||
conin:
|
||
mov si,offset conbuff
|
||
add si,conptr
|
||
lods al
|
||
inc conptr
|
||
;fall thru to upper
|
||
upper: cmp al,'a' ;less than 'a'
|
||
jb upret ;or
|
||
cmp al,'z' ;greater than 'z'
|
||
ja upret ;then no change
|
||
and al,5fh ;else convert to uc
|
||
upret: ret
|
||
;
|
||
ctlchek: ;check for ctl-s, ctl-q and ctl-c
|
||
call constat ;keypress?
|
||
or al,al ;zero?
|
||
jz ctlexit ;no keypress so return
|
||
call consin ;if keypress then get the data
|
||
cmp al,ctls ;check for ctl-s
|
||
jz kwait
|
||
jmp start ;any other key will restart
|
||
kwait: call consin ;if ctl-s then wait for another keypress
|
||
ctlexit:
|
||
ret
|
||
;
|
||
crlf:
|
||
mov al,cr ;send cr and lf to console
|
||
call conout
|
||
mov al,lf
|
||
call conout
|
||
ret
|
||
;
|
||
CRLFCHK: ;DO CRLF AND CHECK FOR ABORT
|
||
CALL CRLF
|
||
CALL CTLCHEK
|
||
RET
|
||
;
|
||
blank: ;print a blank.
|
||
mov al,' '
|
||
call conout
|
||
ret
|
||
;
|
||
tabs: ;print # blanks in cx
|
||
push cx
|
||
call blank
|
||
pop cx
|
||
loop tabs
|
||
ret
|
||
;
|
||
printm: ;print the message at [si] on console
|
||
;end of message indicated by parity set.
|
||
lods al ;get a byte
|
||
test al,80h ;check for end of message
|
||
jnz pquit ;quit if parity set
|
||
push si
|
||
call conout ;otherwise display byte
|
||
pop si
|
||
jmps printm ;print more message
|
||
pquit:
|
||
and al,7fh ;strip parity
|
||
call conout ;print last byte
|
||
ret
|
||
;
|
||
ascout: ;output [al] in ascii
|
||
cmp al,' '
|
||
jb perout ;less than blank?
|
||
cmp al,7eh
|
||
jna ascend
|
||
perout:
|
||
mov al,'.' ;output '.'
|
||
ascend:
|
||
call conout ;else output ascii
|
||
ret
|
||
;
|
||
print8or16: ;print byte or word at es:[si] depending on wmode
|
||
mov ax,es:[si]
|
||
test wmode,1
|
||
jz printbyte
|
||
jmps printword
|
||
;
|
||
printdword: ;print double word as ssss:oooo
|
||
; called with:
|
||
; es = segment
|
||
; di = offset
|
||
push di
|
||
mov ax,es
|
||
call printword ;print segment
|
||
mov al,':'
|
||
call conout
|
||
pop ax
|
||
;
|
||
printword: ;print value in [ax] as 4 hex digits
|
||
push ax
|
||
mov al,ah
|
||
call printbyte
|
||
pop ax
|
||
;
|
||
printbyte: ;print value in [al] as 2 hex digits
|
||
push ax
|
||
mov cl,4
|
||
shr al,cl ;shift al right 4 places
|
||
call printnibble ;output upper nibble
|
||
pop ax ;restore al (now we do lower nibble)
|
||
;
|
||
printnibble: ;print value in low 4 bits of [al] as a hex digit
|
||
and al,0fh ;mask upper 4 bits
|
||
add al,90h
|
||
daa
|
||
adc al,40h
|
||
daa
|
||
call conout
|
||
ret
|
||
;
|
||
; **************************************
|
||
; * *
|
||
; * file name parsing routines *
|
||
; * *
|
||
; **************************************
|
||
;
|
||
parse: ;parse into fcb whose offset is in [di]
|
||
push cs
|
||
pop es ;set es=cs
|
||
push di ;save fcb address
|
||
sub al,al
|
||
mov cx,36 ;fcblen
|
||
rep stos al ;initialize fcb to 0
|
||
pop di ;restore fcb address
|
||
;
|
||
parse2: ;enter here to parse without clearing
|
||
;assumes es = cs from parse:
|
||
mov fcbadr,di ;save fcb address
|
||
inc di ;point to first byte of filename
|
||
call setupdisk ;check for d: and set drive byte
|
||
mov cx,8
|
||
call fillfield ;first item was disk, now get filename
|
||
mov cx,3 ;length of file type
|
||
cmp lastchar,'.'
|
||
jz filltype
|
||
call fillbl ;fill type with blanks if no '.'
|
||
jmps parseret
|
||
filltype:
|
||
call fillfield ;if '.', fill field from console buff
|
||
parseret:
|
||
call scanq ;count '?'s in fcb
|
||
mov al,lastchar
|
||
ret ;with last char scanned in [al]
|
||
parseerr:
|
||
jmp err
|
||
;
|
||
setupdisk: ;set byte 0 of fcb according to char in fcb (1)
|
||
call conin
|
||
mov lastchar,al
|
||
cmp al,' '
|
||
jz setupdisk ;deblank input
|
||
cmp al,eol
|
||
jz s1 ;can't be drive, decrement conptr to rescan
|
||
call conin
|
||
cmp al,':'
|
||
jnz s0 ;not a drive, subtract 2 from conptr to rescan
|
||
mov al,lastchar ;get drive char
|
||
sub al,'A'-1
|
||
dec di ;point to fcb (0)
|
||
stos al ;store drive byte
|
||
ret
|
||
s0:
|
||
dec conptr
|
||
s1:
|
||
dec conptr
|
||
ret
|
||
;
|
||
pdelim: ;check char in [al] for delimiter; return ZF if so.
|
||
mov di,offset delims
|
||
mov cx,ndelims
|
||
repnz scas al ;look in table
|
||
ret
|
||
;
|
||
fillfield: ;count in [cx], dest ptr in [di]
|
||
call conin
|
||
mov lastchar,al ;save last char scanned
|
||
cmp al,'*'
|
||
jnz notast
|
||
call fillq ;fill with '?'
|
||
jmps fillfield ;continue till delimiter
|
||
notast:
|
||
push di
|
||
push cx
|
||
call pdelim
|
||
pop cx
|
||
pop di
|
||
jz fillbl ;if delimiter, fill field with ' '
|
||
jcxz parseerr ;error if count exceeded
|
||
stos al ;store char in fcb
|
||
dec cx ;decrement count
|
||
jmps fillfield
|
||
fillq:
|
||
mov al,'?'
|
||
jmps fillx
|
||
fillbl:
|
||
mov al,' '
|
||
fillx:
|
||
jcxz filldone
|
||
rep stos al ;store '?' or ' '
|
||
filldone:
|
||
ret
|
||
;
|
||
scanq: ;count '?'s in fcb, return ZF set if found
|
||
mov di,fcbadr
|
||
inc di ;point to first char of filename
|
||
mov cx,11 ;11 chars to check
|
||
mov al,'?'
|
||
repnz scas al
|
||
ret
|
||
;
|
||
; ***********************************
|
||
; * *
|
||
; * user CPU state routines *
|
||
; * *
|
||
; ***********************************
|
||
;
|
||
chkreg: ;if reg name in [ax] is valid, return with
|
||
;register number in regnum
|
||
;else go to error processor
|
||
mov cx,totreg+1 ;number of names to check + 1
|
||
mov di,offset regname
|
||
push cs
|
||
pop es
|
||
repnz scas ax
|
||
jcxz checkerr ;not a valid reg name
|
||
mov dx,totreg
|
||
sub dx,cx
|
||
mov regnum,dx ;save reg number
|
||
ret
|
||
;
|
||
checkflag: ;check for valid flag name
|
||
mov cx,nflag+1 ;number of names to check + 1
|
||
mov di,offset flagname
|
||
push cs
|
||
pop es
|
||
repnz scas al
|
||
jcxz checkerr ;not a valid flag name
|
||
mov dx,nflag
|
||
sub dx,cx
|
||
mov regnum,dx ;save flag number
|
||
ret
|
||
;
|
||
checkerr:
|
||
jmp err
|
||
;
|
||
setreg: ;set reg whose number is in [cx] to value in [ax]
|
||
mov si,offset userreg
|
||
add si,cx
|
||
add si,cx
|
||
mov [si],ax
|
||
ret
|
||
;
|
||
printflags: ;print values of flags
|
||
mov cx,0
|
||
pf0:
|
||
push cx ;save count
|
||
call printflag
|
||
pop cx
|
||
inc cx
|
||
cmp cx,9
|
||
jb pf0
|
||
ret
|
||
;
|
||
setflag: ;set flag whose # is in [cx] to value in [bx]
|
||
mov si,offset flagbits
|
||
add si,cx
|
||
lods al
|
||
mov cl,al
|
||
mov ax,0fffeh
|
||
ror ax,cl
|
||
ror bx,cl
|
||
and userfl,ax
|
||
or userfl,bx
|
||
ret
|
||
;
|
||
printflagname: ;print flag name whose # is in [cx]
|
||
mov si,offset flagname
|
||
add si,cx
|
||
lods al ;get flag name
|
||
call conout
|
||
ret
|
||
;
|
||
getflag: ;check flag whose # is in [cx]
|
||
;return with ZF set if flag is set
|
||
mov ax,1
|
||
mov si,offset flagbits
|
||
add si,cx
|
||
mov cl,[si] ;get flagbits (flagnum)
|
||
ror ax,cl ;get mask into position
|
||
and ax,userfl ;see if bit set in CPU state
|
||
ret
|
||
;
|
||
printflagval: ;print value of flag (as 0 or 1) whose # is in [cx]
|
||
call getflag
|
||
mov al,'0'
|
||
jz pf2 ;if flag not set, print '0'
|
||
mov al,'1' ;else print '1'
|
||
pf2:
|
||
call conout
|
||
ret
|
||
;
|
||
printflag: ;print flag (as flagname of '-') whose # is in [cx]
|
||
mov si,offset flagname
|
||
add si,cx ;point to flag name
|
||
push word ptr [si] ;save flag char
|
||
call getflag
|
||
pop ax ;get flag char
|
||
jnz pname ;if flag set, use flag char
|
||
mov al,'-' ;else print hyphen
|
||
pname:
|
||
call conout
|
||
ret
|
||
;
|
||
PREG1: ;PRINT FIRST 6 REGISTER NAMES (FOR 40 COLUMNS)
|
||
MOV CX,0
|
||
MOV NREG,6
|
||
JMPS PR0
|
||
PREG2: ;PRINT NEXT 7 REGISTER NAMES (FOR 40 COLUMNS)
|
||
MOV CX,6
|
||
JMPS PR00
|
||
printregs: ;print register values
|
||
mov cx,0
|
||
PR00:
|
||
MOV NREG,13
|
||
pr0:
|
||
call testregcl ;see if reg should be printed
|
||
jnb pr2 ;don't print if carry not set
|
||
push cx
|
||
call printregval
|
||
call blank
|
||
pop cx
|
||
pr2:
|
||
inc cx
|
||
CMP CL,NREG
|
||
jb pr0
|
||
ret
|
||
;
|
||
printregval: ;print value of reg whose # is in [cx]
|
||
mov si,offset userreg
|
||
add si,cx
|
||
add si,cx
|
||
lods ax
|
||
call printword
|
||
ret
|
||
;
|
||
printregname: ;print name of reg whose # is in [cx]
|
||
mov si,offset regname
|
||
add si,cx
|
||
add si,cx
|
||
call printm
|
||
ret
|
||
;
|
||
testregcl: ;see if reg whose # is in [cl] should be printed
|
||
;return with carry set if so
|
||
test segflag,0ffh
|
||
jnz printit ;print all reg's if segflag set
|
||
cmp cl,11 ;otherwise, see if [cl] has seg reg #
|
||
ja printit
|
||
cmp cl,8
|
||
ret
|
||
printit:
|
||
stc
|
||
ret
|
||
;
|
||
SETUPHDR:
|
||
call crlf
|
||
mov cx,11
|
||
call tabs ;leave space for flags
|
||
mov cx,0
|
||
RET
|
||
;
|
||
PREGHDR1: ;PRINT HEADER FOR FIRST 6 REGS (FOR 40 COL)
|
||
CALL SETUPHDR
|
||
MOV NREG,6
|
||
JMPS PRH0
|
||
PREGHDR2: ;PRINT HEADER FOR NEXT 7 REGISTERS
|
||
CALL BLANK
|
||
MOV CX,6
|
||
JMPS PRH00
|
||
printregheader: ;print header for registers
|
||
CALL SETUPHDR
|
||
PRH00:
|
||
MOV NREG,13
|
||
prh0:
|
||
call testregcl ;see if reg should be printed
|
||
jnb prh1 ;don't print if carry not set
|
||
push cx
|
||
call printregname
|
||
mov cx,3
|
||
call tabs
|
||
pop cx
|
||
prh1:
|
||
inc cx
|
||
CMP CL,NREG
|
||
jb prh0
|
||
ret
|
||
;
|
||
printinstr: ;disassemble instruction at [cs:ip]
|
||
mov es,usercs
|
||
mov si,userip
|
||
test disempresent,0ffh
|
||
jz pi1
|
||
push es
|
||
push si
|
||
test segflag,0ffh
|
||
jz pi0
|
||
call crlf
|
||
pi0:
|
||
call disem
|
||
ret
|
||
pi1:
|
||
mov al,es:[si]
|
||
call printbyte
|
||
ret
|
||
;
|
||
printseginfo: ;print name, start and end address of segment whose
|
||
;number is in [al] if length is non-zero.
|
||
mov cl,al ;save seg number
|
||
mov bl,6
|
||
mul bl ;6 bytes per segment in base page
|
||
add ax,offset basepagesave
|
||
mov si,ax ;si now points to entry in base page
|
||
lods ax ;get low 16 bits of length
|
||
mov bx,ax ;save in bx
|
||
lods al ;get high nibble of length
|
||
mov dl,al ;save it
|
||
mov ah,0
|
||
or ax,bx ;test for zero length
|
||
jz psiret ;if zero, no display
|
||
lods ax ;get base
|
||
push bx ;save low (length)
|
||
push dx ;save high (length)
|
||
push ax ;save base
|
||
mov ch,0 ;zero high byte of segment #
|
||
shl cx,1 ;* 2 (2 bytes per segment name)
|
||
add cx,offset segnames ;cx now points to segment name
|
||
push cx ;save it
|
||
call crlf
|
||
pop si
|
||
call printm ;print segment name
|
||
call blank
|
||
pop es ;get base
|
||
push es ;save base
|
||
mov di,0
|
||
call printdword ;print start address
|
||
call blank
|
||
pop bx ;get base
|
||
pop ax ;get high (len)
|
||
mov cl,12
|
||
shl ax,cl ;move ls nibble of al to ms nibble of ah
|
||
add ax,bx ;add ms nibble of length to base
|
||
mov es,ax
|
||
pop di ;get low (len)
|
||
call printdword ;print end address
|
||
psiret:
|
||
ret
|
||
;
|
||
setcpustate: ;set users regs after E command
|
||
MOV AX,CCPSS
|
||
MOV USERSS,AX
|
||
MOV AX,CCPSP
|
||
MOV USERSP,AX ;RESET USER STACK POINTER TO CCP STACK
|
||
mov ax,bx ;get ds base in [ax] (returned from bdos load)
|
||
mov userds,ax ;set user's ds
|
||
mov usercs,ax
|
||
mov useres,ax
|
||
mov type1seg,ax
|
||
mov type2seg,ax
|
||
mov es,ax
|
||
test es:byte ptr .5, 1 ;test 8080 flag
|
||
jz not8080
|
||
mov ax,100h ;default for userip, lasloc, disloc
|
||
jmps setdone
|
||
not8080:
|
||
mov ax,es:.3 ;get cs base
|
||
mov usercs,ax
|
||
mov type1seg,ax
|
||
mov ax,es:.15 ;get es base
|
||
or ax,ax
|
||
jz sc1
|
||
mov useres,ax ;set it if there was one
|
||
sc1:
|
||
mov ax,es:.21 ;get ss base
|
||
or ax,ax
|
||
jz setdone
|
||
mov userss,ax ;set it if there was one
|
||
mov ax,es:.18 ;get stack length
|
||
mov usersp,ax ;set user's sp
|
||
sub ax,ax ;userip, lasloc, disloc = 0 for non-8080 model
|
||
setdone:
|
||
mov userip,ax
|
||
mov lasloc,ax
|
||
ret
|
||
;
|
||
; *********************************************
|
||
; * *
|
||
; * breakpoint/single step procedures *
|
||
; * *
|
||
; *********************************************
|
||
;
|
||
setbp: ;set breakpoint at address stored in dword at [di]
|
||
les si,[di] ;point [es]:[si] to breakpoint location
|
||
mov al,0cch ;int 3 instruction
|
||
xchg al,es:[si] ;set breakpoint and fetch instruction
|
||
mov 4[di],al ;save user instruction in breakpoint table
|
||
inc bpcnt ;increment breakpoint count
|
||
ret
|
||
;
|
||
bpclear: ;clear breakpoint table
|
||
sub cx,cx
|
||
mov cl,bpcnt ;get # of bp's to clear
|
||
mov si,offset brk1loc ;point to bp table
|
||
bpcloop:
|
||
jcxz bpend ;0..quit
|
||
lods ax ;get bp offset
|
||
push ax ;save it
|
||
lods ax ;get bp segment
|
||
mov es,ax
|
||
lods al ;get inst byte
|
||
pop di ;get bp offset
|
||
stos al ;store user instruction back
|
||
loop bpcloop
|
||
mov bpcnt,0 ;zero bp counter
|
||
bpend: ret
|
||
;
|
||
BPV:
|
||
TEST SAVEVECFLAG,0FFH
|
||
JZ BPVECTRET
|
||
bpvect: ;set up breakpoint/single step vectors
|
||
call savevect
|
||
mov dx,0
|
||
mov es,dx ;make sure dest is absolute 0
|
||
mov di,4 ;set up single step vector
|
||
mov ax,offset ssentry ;single step entry point
|
||
stos ax ;save at ss vector
|
||
mov ax,cs
|
||
stos ax ;save cs
|
||
mov di,12 ;set up breakpoint vector
|
||
mov ax,offset breakentry ;set up bp vector
|
||
stos ax ;save at bp vector
|
||
mov ax,cs
|
||
stos ax ;save cs
|
||
BPVECTRET:
|
||
ret
|
||
;
|
||
savevect: ;save previous contents of 0:4 thru 0:f
|
||
mov si,4
|
||
mov di,offset vectorsave
|
||
push ds
|
||
pop es ;point to ddt segment
|
||
mov cx,12
|
||
push ds
|
||
mov dx,0
|
||
mov ds,dx
|
||
rep movs al,al
|
||
pop ds
|
||
svret:
|
||
ret
|
||
;
|
||
restorevect: ;restore previous contents of 0:4 thru 0:f
|
||
test savevecflag,0ffh
|
||
jz rvret
|
||
mov si,offset vectorsave
|
||
mov di,4
|
||
mov cx,12
|
||
mov dx,0
|
||
mov es,dx
|
||
rep movs al,al
|
||
rvret:
|
||
ret
|
||
;
|
||
SETDEFSEG: ;SET DEFAULT TYPE1SEG, LASLOC
|
||
mov di,userip
|
||
mov lasloc,di ;set disassembler offset
|
||
mov es,usercs
|
||
mov type1seg,es ;set type1seg segment
|
||
RET
|
||
;
|
||
breakaddr: ;print address where break occurred
|
||
call crlf
|
||
mov al,'*'
|
||
call conout
|
||
mov ax,userds
|
||
mov type2seg,ax ;set type2 segment to userds
|
||
CALL SETDEFSEG
|
||
call printdword ;print break address
|
||
ret
|
||
;
|
||
breakentry: ;breakpoint entry
|
||
mov breakfl,1
|
||
jmps savecpu ;common code for break and single step
|
||
ssentry: ;single step entry
|
||
mov breakfl,0
|
||
savecpu:
|
||
mov userax,ax
|
||
mov userbx,bx
|
||
mov usercx,cx
|
||
mov userdx,dx
|
||
mov usersi,si
|
||
mov userdi,di
|
||
mov userbp,bp
|
||
mov usersp,sp
|
||
mov useres,es
|
||
mov userds,ds
|
||
mov userss,ss
|
||
mov bp,sp
|
||
mov ax,[bp]
|
||
mov userip,ax
|
||
mov ax,2[bp]
|
||
mov usercs,ax
|
||
mov ax,4[bp]
|
||
mov userfl,ax
|
||
;
|
||
mov ax,cs
|
||
mov ds,ax
|
||
mov ss,ax
|
||
mov sp,offset stackp
|
||
;
|
||
test sysif,ifmask8 ;see whether interrupts should be enabled
|
||
jz sav0
|
||
sti
|
||
sav0:
|
||
add usersp,6 ;to make up for stacked cs, ip, and fl
|
||
cld
|
||
call restorevect
|
||
test breakfl,0ffh
|
||
jz sst0
|
||
;
|
||
break0: ;continuation of break processing
|
||
dec userip ;adjust user ip for breakpoint instr
|
||
call bpclear ;clear all breakpoints
|
||
test skipbdos,0ffh ;were we originally in trace mode?
|
||
jnz sst00 ;if so, continue tracing
|
||
;
|
||
tracedone:
|
||
call breakaddr
|
||
jmp start
|
||
;
|
||
sst00: ;get here on breakpoint on return from bdos
|
||
mov skipbdos,0 ;no longer tracing thru bdos
|
||
sst0: ;continuation of single step processing
|
||
and userfl,0feffh ;clear user trap flag
|
||
TEST USERIFOFF,1
|
||
JZ SST1
|
||
MOV USERIFOFF,0
|
||
OR USERFL,200H ;RESTORE USER IF
|
||
SST1:
|
||
dec tracecount
|
||
jz tracedone
|
||
CALL CTLCHEK ;CHECK FOR ABORT
|
||
test traceprint,0ffh
|
||
jz tracerestore
|
||
call xnohdr ;display regs without header
|
||
;
|
||
tracerestore: ;enter here when in trace mode
|
||
mov es,usercs
|
||
mov si,userip
|
||
mov ax,word ptr .bdosintloc ;get bdos interrupt instruction
|
||
cmp ax,es:[si] ;see if instruction to be traced is bdos int
|
||
jnz tr00
|
||
mov brk1seg,es
|
||
add si,2 ;point to instruction after bdos int
|
||
mov brk1loc,si
|
||
mov di,offset brk1loc
|
||
call setbp ;set breakpoint at return from bdos
|
||
mov skipbdos,1 ;so we know we were in trace mode when we hit bp
|
||
jmps rstore ;without setting single step flag
|
||
tr00:
|
||
MOV AX,USERFL
|
||
OR AX,100H ;SET TRACE FLAG
|
||
TEST AX,200H ;IS USER IF SET?
|
||
JZ TR01
|
||
AND AX,NOT 200H ;CLEAR IT (SO WE DON'T END UP IN INT HANDLER)
|
||
MOV ES,USERCS
|
||
MOV SI,USERIP
|
||
MOV BL,ES:[SI] ;GET INSTRUCTION TO EXECUTE
|
||
CMP BL,0FAH ;IS IT CLI?
|
||
JZ TR01
|
||
CMP BL,0CFH ;IRET?
|
||
JZ TR01
|
||
CMP BL,09DH ;POPF?
|
||
JZ TR01
|
||
CMP BL,0CDH ;INT?
|
||
JZ TR01
|
||
MOV USERIFOFF,1 ;SET FLAG SO DDT86 WILL TURN IF BACK ON
|
||
TR01:
|
||
MOV USERFL,AX
|
||
rstore: ;enter here when in G mode
|
||
CALL BPV
|
||
cli
|
||
mov sp,offset userreg ;point to reg save area
|
||
pop ax
|
||
pop bx
|
||
pop cx
|
||
pop dx
|
||
pop savesp
|
||
pop bp
|
||
pop si
|
||
pop di
|
||
pop ds ;throw away cs
|
||
pop ds
|
||
pop savess
|
||
pop es
|
||
mov ss,savess ;restore stack
|
||
mov sp,savesp
|
||
push userfl ;flags
|
||
push usercs ;cs
|
||
push userip ;ip
|
||
iret ;transfer to user program
|
||
;
|
||
; **********************************
|
||
; * *
|
||
; * miscellaneous routines *
|
||
; * *
|
||
; **********************************
|
||
;
|
||
delim:
|
||
cmp al,eol
|
||
jz delret
|
||
cmp al,','
|
||
jz delret
|
||
cmp al,' '
|
||
jz delret
|
||
cmp al,':'
|
||
delret:
|
||
ret
|
||
;
|
||
hexcon:
|
||
sub al,'0'
|
||
cmp al,10
|
||
jb hexret
|
||
add al,('0' - 'A' + 10) and 0ffh
|
||
cmp al,16
|
||
jnb hexerr
|
||
cmp al,10
|
||
jb hexerr
|
||
hexret:
|
||
ret
|
||
hexerr:
|
||
jmp err
|
||
;
|
||
plmset: ;get here when assembler wants to set memory
|
||
mov bp,sp ;for parameter fetching
|
||
mov ax,2[bp] ;get value in [al]
|
||
mov es,type1seg ;segment used in A command is in type1 seg
|
||
mov di,4[bp] ;get offset from stack
|
||
call setbyte ;set and verify
|
||
inc di ;increment offset
|
||
jnz psret ;if incremented offset is non-zero, return
|
||
jmp start ;otherwise exit A command, since wrap occurred
|
||
psret:
|
||
ret 4 ;remove 2 parameters
|
||
;
|
||
set8or16: ;set byte or word at es:[di] depending on wmode
|
||
test wmode,1
|
||
jz setbyte
|
||
;fall through to setword
|
||
;
|
||
setword: ;set word at es:[di] to [ax] and verify
|
||
;
|
||
; NOTE: THIS CODE COULD BE REPLACED BY THE FOLLOWING 4 INSTRUCTIONS
|
||
; FOR SYSTEMS IN WHICH MEMORY CAN ONLY BE ADDRESSED BY WORDS.
|
||
; HOWEVER, THIS WILL WRAP AROUND AND MODIFY LOCATIONS 0 IF
|
||
; [DI] CONTAINS 0FFFEH.
|
||
;
|
||
; MOV ES:[DI],AX
|
||
; CMP ES:[DI],AX
|
||
; JNZ BADVER
|
||
; RET
|
||
;
|
||
push ax ;save hi byte
|
||
call setbyte ;set low byte
|
||
pop ax
|
||
mov al,ah
|
||
inc di ;point to next location
|
||
jz sret ;don't set byte if wraparound occurred
|
||
;fall thru to setbyte
|
||
;
|
||
setbyte: ;set byte at es:[di] to [al] and verify
|
||
mov es:[di],al ;store byte
|
||
cmp es:[di],al ;see if it got stored
|
||
jnz badver
|
||
sret:
|
||
ret
|
||
;
|
||
badver:
|
||
push di
|
||
push es
|
||
mov si,offset verm
|
||
call printm ;print verify error message
|
||
pop es
|
||
pop di
|
||
call printdword
|
||
jmp start
|
||
;
|
||
inc1or2: ;inc pointer at [si] by 1 or 2, depending on wmode
|
||
;return with carry flag set if wrap occurred
|
||
mov al,wmode
|
||
and ax,1 ;mask to 0 or 1
|
||
inc ax ;increment value is now 1 or 2
|
||
add [si],ax ;increment pointer
|
||
cmp [si],ax ;test for wraparound
|
||
ret
|
||
;
|
||
getnumber: ;get number from input buffer
|
||
;returns:
|
||
;bx = value of number from input
|
||
;al = last character scanned (delimiter)
|
||
;ah = blank flag (0 = blank, 1 = non-blank)
|
||
sub bx,bx ;initialize value to 0
|
||
mov ah,bh ;initialize blank flag to blank
|
||
getn0:
|
||
call conin
|
||
call delim ;check for delimiter
|
||
jz getnret ;delimiter found, exit
|
||
mov cl,4
|
||
shl bx,cl ;make room for new nibble
|
||
call hexcon ;convert ascii to binary
|
||
add bl,al ;add nibble
|
||
mov ah,1 ;blank flag = non-blank
|
||
jmps getn0
|
||
getnret:
|
||
ret
|
||
;
|
||
getoffset: ;get offset from input line
|
||
;offset is a non-blank number not followed by ':'
|
||
;returns:
|
||
;al = last char scanned (delimiter)
|
||
;bx = value
|
||
call getnumber ;get value to bx
|
||
or ah,ah ;check for blank entry
|
||
jz geterr ;don't allow blank entry
|
||
cmp al,':' ;check delimiter for ':'
|
||
jz geterr ;don't allow ':' delimiter
|
||
ret
|
||
;
|
||
getlastoffset: ;same as getoffset but delimiter must be a cr
|
||
call getoffset
|
||
cmp al,eol
|
||
jnz geterr
|
||
ret
|
||
geterr:
|
||
jmp err
|
||
;
|
||
checkword: ;check for 'W' following command letter
|
||
call conin
|
||
cmp al,'W'
|
||
jnz chret
|
||
mov wmode,1
|
||
ret
|
||
chret: dec conptr ;to rescan character
|
||
ret
|
||
;
|
||
checkreg: ;check for valid segment register prefix - <sr>:
|
||
;called with:
|
||
;bl = first char
|
||
;bh = second char
|
||
;returns:
|
||
;si = offset to register, if found
|
||
;zf = found flag (1 = found, 0 = not found)
|
||
or bh,80h ;since they are defined like that
|
||
mov bp,offset segreg ;point to seg reg names
|
||
sub si,si ;initialize index to 0
|
||
check0:
|
||
cmp bx,[bp+si] ;is it a seg reg name
|
||
jz checkret
|
||
add si,2 ;point to next name
|
||
cmp si,8 ;check for done (4 seg reg names)
|
||
jnz check0
|
||
or si,si ;unset zero flag
|
||
checkret:
|
||
ret
|
||
;
|
||
checksegreg: ;check for valid seg reg name
|
||
;if found, return contents of seg reg
|
||
;else reset input pointer for rescan
|
||
;returns:
|
||
;dx = seg reg value
|
||
;zf = valid seg reg (1 = valid, 0 = not valid)
|
||
push conptr ;save input pointer for possible rescan
|
||
call conin
|
||
push ax
|
||
call conin
|
||
push ax
|
||
call conin
|
||
cmp al,':' ;valid seg reg must have colon
|
||
pop bx
|
||
pop cx
|
||
mov bh,cl
|
||
xchg bl,bh
|
||
jnz notsr
|
||
call checkreg ;see if it's a valid name
|
||
jnz notsr
|
||
mov bp,offset usercs ;point to saved user seg reg's
|
||
mov dx,[bp+si] ;get value of user seg reg
|
||
pop cx ;throw away saved input pointer
|
||
ret
|
||
notsr:
|
||
pop conptr ;reset for rescan
|
||
ret
|
||
;
|
||
getsegandoff: ;get user location specification
|
||
;may be one of the following forms:
|
||
;<empty>
|
||
;nnnn
|
||
;sr:nnnn
|
||
;mmmm:nnnn
|
||
;if numreq set, <empty> is invalid
|
||
;called with:
|
||
;di = offset of 4 byte area containing <offset><segment>
|
||
;numreq must have been initialized by calling routine
|
||
call checksegreg ;see if there is a segment prefix
|
||
jz gets0
|
||
call getnumber ;no segment prefix, check for number
|
||
or ah,ah ;was there one?
|
||
jz gets3
|
||
mov dx,bx ;move number to dx
|
||
cmp al,':' ;was delimiter a ':'
|
||
jnz gets2
|
||
gets0:
|
||
call getoffset ;segment prefix present, must have number
|
||
mov [di],bx ;number goes to <offset>
|
||
mov 2[di],dx ;first number (or sr) goes to <segment>
|
||
ret
|
||
gets2:
|
||
mov [di],dx ;only one number, put it in <offset>
|
||
getsret:
|
||
ret
|
||
gets3:
|
||
test numreq,0ffh ;blank field, see if ok
|
||
jz getsret ;ok, return with no change at [di]
|
||
jmp err ;number was required
|
||
;
|
||
; *****************************
|
||
; * *
|
||
; * disk i/o routines *
|
||
; * *
|
||
; *****************************
|
||
;
|
||
readfile: ;read file in fcb into memory described in mcb
|
||
;when done, mcb will have base and length of block to free
|
||
mov ax,mcbbase
|
||
mov startreadseg,ax
|
||
mov endreadseg,ax
|
||
mov dmaseg,ax
|
||
sub ax,ax
|
||
mov startreadoff,ax
|
||
mov endreadoff,ax
|
||
rf0:
|
||
mov dx,dmaseg
|
||
call setdmab ;set dma base
|
||
mov dmaoff,0
|
||
rf1:
|
||
mov dx,dmaoff
|
||
call setdma ;set dma offset
|
||
cmp mcblen,8 ;8 paragraphs per sector
|
||
jb readerr ;if less than 8 pp's left, not enough memory
|
||
mov dx,offset fcb
|
||
call readsec
|
||
or al,al ;test value returned from bdos
|
||
jnz readdone
|
||
add mcbbase,8 ;point mcb to next available paragraph
|
||
sub mcblen,8 ;decrement # of available paragraphs
|
||
mov ax,dmaoff
|
||
add al,7fh ;add sector size - 1
|
||
mov endreadoff,ax
|
||
MOV AX,DMASEG
|
||
MOV ENDREADSEG,AX
|
||
add dmaoff,80h ;increment dma offset
|
||
jnz rf1 ;if no wrap occurred, simply continue
|
||
add dmaseg,1000h ;else increment dma segment
|
||
jmps rf0
|
||
readdone:
|
||
MOV DX,OFFSET FCB
|
||
CALL CLOSE
|
||
ret
|
||
readerr:
|
||
jmp loaderr
|
||
;
|
||
writefile: ;write block at startwriteloc - endwriteloc to file in fcb
|
||
mov ax,startwriteoff
|
||
mov cl,4
|
||
shr ax,cl ;divide offset by 16 - truncate ls nibble
|
||
add ax,startwriteseg ;compute absolute paragraph number
|
||
mov mcbbase,ax
|
||
mov dmaseg,ax
|
||
mov bx,ax ;store start paragraph # in [bx]
|
||
mov ax,endwriteoff
|
||
shr ax,cl
|
||
add ax,endwriteseg ;calculate absolute paragraph number of end
|
||
sub ax,bx ;compute # of paragraphs to write
|
||
jb wferr ;start can't be > end
|
||
mov mcblen,ax ;store # paragraphs to write
|
||
mov dx,offset fcb
|
||
call delete
|
||
TEST ERRMODE,0FFH
|
||
JZ WF00
|
||
INC AL ;DID DELETE RETURN 0FFH?
|
||
JNZ WF00 ;IF NOT, OK
|
||
OR AH,AH ;SEE IF EXTENDED OR PHYSICAL ERROR
|
||
JNZ WFERR ;IF SO, DON'T CONTINUE
|
||
WF00:
|
||
mov dx,offset fcb
|
||
call make
|
||
wf0:
|
||
mov dx,dmaseg
|
||
call setdmab
|
||
mov dmaoff,0 ;clear dma offset
|
||
wf1:
|
||
mov dx,dmaoff
|
||
call setdma
|
||
mov dx,offset fcb
|
||
call writesec
|
||
sub mcblen,8 ;8 paragraphs per sector
|
||
jb writedone
|
||
add dmaoff,80h ;increment dma pointer
|
||
jnz wf1 ;loop if no wrap occurred
|
||
add dmaseg,1000h ;if wrap occurred, increment dma segment
|
||
jmps wf0
|
||
writedone:
|
||
ret
|
||
wferr:
|
||
jmp err
|
||
;
|
||
eject
|
||
;
|
||
; **********************************
|
||
; * *
|
||
; * a - assemble mnemonics *
|
||
; * *
|
||
; **********************************
|
||
;
|
||
assm:
|
||
test assempresent,0ffh
|
||
jz asmerr
|
||
mov asmspsav,sp ;save in case of error in pl/m
|
||
mov di,offset type1loc
|
||
call getsegandoff ;get start address
|
||
asm0:
|
||
push type1seg ;for pl/m call
|
||
push type1loc ;for pl/m call
|
||
call assem ;returns offset of next available byte
|
||
cmp ax,type1loc ;test for no input
|
||
jna asmret ;done unless greater than original type1loc
|
||
mov type1loc,ax ;update type1loc
|
||
jmps asm0
|
||
asmret:
|
||
ret
|
||
asmerr:
|
||
jmp err
|
||
asment: ;arrive here on input error in pl/m
|
||
mov sp,asmspsav ;reset stack to where it was
|
||
jmps asm0 ;go back for more input
|
||
;
|
||
; *****************************
|
||
; * *
|
||
; * B - BLOCK COMPARE *
|
||
; * *
|
||
; *****************************
|
||
;
|
||
BLOCKCOMPARE:
|
||
mov di,offset type2loc
|
||
call getsegandoff
|
||
call getoffset ;get end offset
|
||
mov usermax,bx
|
||
cmp al,eol
|
||
jz cmperr ;need 3 arguments
|
||
sub bx,type2loc
|
||
jb cmperr ;error if start > end
|
||
mov ax,type2seg
|
||
mov userseg2,ax ;default to same seg as source
|
||
mov di,offset userloc2
|
||
call getsegandoff ;get destination address
|
||
cmp al,eol
|
||
jnz cmperr ;error if more than 3 arguments
|
||
CMP0:
|
||
LES SI,DWORD PTR TYPE2LOC
|
||
MOV AL,ES:[SI]
|
||
LES SI,DWORD PTR USERLOC2
|
||
CMP AL,ES:[SI]
|
||
JZ CMPCONT
|
||
CALL CRLFCHK
|
||
MOV DI,OFFSET TYPE2LOC
|
||
CALL PRINTERROR
|
||
CALL BLANK
|
||
CALL BLANK
|
||
MOV DI,OFFSET USERLOC2
|
||
CALL PRINTERROR
|
||
CMPCONT:
|
||
INC TYPE2LOC
|
||
MOV AX,TYPE2LOC
|
||
CMP USERMAX,AX
|
||
JC CMPDONE
|
||
INC USERLOC2
|
||
JZ CMPDONE ;PREVENT WRAPAROUND
|
||
JMPS CMP0
|
||
;
|
||
CMPDONE:
|
||
RET
|
||
CMPERR:
|
||
JMP ERR
|
||
;
|
||
PRINTERROR: ;PRINT DWORD AT [DI], BYTE POINTED TO BY DWORD
|
||
LES DI,[DI]
|
||
MOV AL,ES:[DI]
|
||
PUSH AX ;SAVE BYTE AT ES:DI
|
||
CALL PRINTDWORD
|
||
CALL BLANK
|
||
POP AX
|
||
CALL PRINTBYTE
|
||
RET
|
||
;
|
||
; ******************************
|
||
; * *
|
||
; * d - display memory *
|
||
; * *
|
||
; ******************************
|
||
;
|
||
display:
|
||
mov numreq,0 ;ok to have no entries
|
||
mov ax,type2seg
|
||
mov disseg,ax ;default to type2 seg
|
||
call checkword
|
||
TEST COL40,0FFH
|
||
JZ DIS01
|
||
TEST WMODE,1
|
||
JNZ DIS00
|
||
MOV AL,ND40
|
||
JMPS DIS02
|
||
DIS00:
|
||
MOV AL,NDW40 ;CHARS PER LINE FOR DW IN 40 COL MODE
|
||
JMPS DIS02
|
||
DIS01:
|
||
MOV AL,ND80 ;16 BYTES PER LINE IN NORMAL MODE
|
||
DIS02:
|
||
MOV LINEMAX,AL
|
||
mov di,offset disloc
|
||
call getsegandoff
|
||
cmp al, ','
|
||
mov ax,disseg
|
||
mov type2seg,ax ;update default type2 seg
|
||
jnz dis0 ;must be cr, no dismax entered
|
||
call getlastoffset ;get dismax
|
||
jmps dis1
|
||
dis0:
|
||
mov bx,disloc ;no dismax entered, calculate default
|
||
MOV AL,LINEMAX
|
||
MOV CL,NLINES
|
||
MUL CL
|
||
DEC AL
|
||
ADD BX,AX
|
||
cmp bx,disloc ;see if we went over ffff
|
||
jnb dis1
|
||
mov bx,0ffffh ;set dismax if we wrapped around
|
||
dis1:
|
||
mov dismax,bx
|
||
disp3:
|
||
CALL CRLFCHK
|
||
les di,dword ptr disloc
|
||
mov tdisp,di
|
||
call printdword
|
||
disp4:
|
||
call blank
|
||
les si,dword ptr disloc
|
||
call print8or16
|
||
mov si,offset disloc
|
||
call inc1or2
|
||
jb disp6 ;stop if wrap occurred
|
||
mov ax,disloc
|
||
sub ax,tdisp ;calculate # bytes printed on line
|
||
CMP AL,LINEMAX ;SEE IF LINE FULL
|
||
jz disp6
|
||
mov ax,disloc
|
||
cmp ax,dismax ;check for done
|
||
jna disp4
|
||
disp6:
|
||
call blank
|
||
disp7:
|
||
mov es,disseg
|
||
mov si,tdisp
|
||
mov al,es:[si]
|
||
call ascout
|
||
inc tdisp
|
||
jz disp8 ;stop if wrap occurred
|
||
mov ax,tdisp
|
||
cmp ax,disloc
|
||
jnz disp7
|
||
cmp ax,dismax
|
||
ja disp8
|
||
jmps disp3
|
||
disp8:
|
||
ret
|
||
;
|
||
; ******************************************
|
||
; * *
|
||
; * e - load program for execution *
|
||
; * *
|
||
; ******************************************
|
||
;
|
||
cmd db 'CMD'
|
||
;
|
||
execute:
|
||
call conin
|
||
cmp al,eol ;check for no filename
|
||
jz eerr ;don't allow no filename
|
||
dec conptr ;to rescan character
|
||
mov di,offset fcb
|
||
call parse
|
||
jz eerr ;no '?' or '*' allowed
|
||
cmp al,eol
|
||
jnz eerr ;eol must follow filename
|
||
push cs
|
||
pop es ;set es = cs
|
||
cmp es:fcb+9, ' ' ;see if filetype blank
|
||
jnz ex0
|
||
mov si,offset cmd
|
||
mov di,offset fcb+9
|
||
mov cx,3
|
||
rep movs al,al ;set filetype to 'CMD' if empty
|
||
ex0:
|
||
mov dx,offset fcb
|
||
call open ;see if file exists
|
||
mov mcbext,0ffh ;free all allocations below DDT86
|
||
mov dx,offset mcb
|
||
call freemem ;free all memory previously allocated under DDT
|
||
mov dx,offset fcb
|
||
call load ;load user program
|
||
push bx ;save ds base
|
||
call setcpustate
|
||
pop dx ;get ds base back
|
||
call setdmab ;set dma base
|
||
mov dx,80h
|
||
call setdma ;default to 80h in user's DS
|
||
MOV DX,OFFSET FCB
|
||
CALL CLOSE
|
||
mov mode,'E'
|
||
mov si,0
|
||
mov di,offset basepagesave
|
||
push ds
|
||
pop es ;set es to ddt's segment
|
||
mov ax,userds
|
||
push ds ;save it
|
||
mov ds,ax
|
||
mov cx,48
|
||
rep movs al,al ;copy user's base page into ddt save area
|
||
pop ds ;restore ds
|
||
call verify ;display load info
|
||
DEC CONPTR ;TO RESCAN CR
|
||
JMP IFCB ;TO CLEAR FCB
|
||
eerr:
|
||
jmp err
|
||
;
|
||
; ***************************
|
||
; * *
|
||
; * f - fill memory *
|
||
; * *
|
||
; ***************************
|
||
;
|
||
fill:
|
||
call checkword ;check for 'FW'
|
||
mov di,offset type2loc
|
||
call getsegandoff
|
||
call getoffset ;get end address
|
||
mov usermax,bx ;save end address
|
||
call getlastoffset ;get fill constant
|
||
test wmode,1
|
||
jnz fil0
|
||
or bh,bh ;if not wmode, high byte must be 0
|
||
jnz filerr
|
||
fil0:
|
||
mov cx,usermax ;get end address
|
||
sub cx,type2loc ;compare for valid range
|
||
jb filerr ;error if start > end
|
||
fil1:
|
||
les di,dword ptr type2loc
|
||
mov ax,bx ;get fill constant
|
||
call set8or16
|
||
mov si,offset type2loc
|
||
call inc1or2
|
||
jb filret ;stop if wrap occurred
|
||
mov ax,type2loc
|
||
cmp ax,usermax
|
||
jbe fil1
|
||
filret:
|
||
ret
|
||
filerr:
|
||
jmp err
|
||
;
|
||
; **********************************
|
||
; * *
|
||
; * g - go to user program *
|
||
; * *
|
||
; **********************************
|
||
;
|
||
gouser:
|
||
mov ax,usercs
|
||
mov goseg,ax ;default goseg = usercs
|
||
mov ax,userip
|
||
mov goloc,ax ;default goloc = userip
|
||
mov numreq,0 ;number not required in G command
|
||
mov di,offset goloc
|
||
call getsegandoff ;get start address
|
||
cmp al,eol
|
||
jz gorestore ;if eol, no breakpoints set
|
||
mov ax,goseg
|
||
mov brk1seg,ax
|
||
mov brk2seg,ax ;defaults for breakpoint segments = goseg
|
||
mov di,offset brk1loc
|
||
call getsegandoff ;get first breakpoint
|
||
push ax ;save terminating char
|
||
mov di,offset brk1loc
|
||
call setbp ;save breakpoint in table
|
||
pop ax ;get char
|
||
cmp al,eol
|
||
jz gorestore ;only one breakpoint
|
||
mov di,offset brk2loc
|
||
call getsegandoff ;get second breakpoint
|
||
cmp al,eol
|
||
jnz goerr ;only 2 breakpoints allowed
|
||
mov di,offset brk2loc
|
||
call setbp ;set second breakpoint
|
||
gorestore:
|
||
mov skipbdos,0 ;make sure it's 0 since we aren't in T/U mode
|
||
mov ax,goseg
|
||
mov usercs,ax ;usercs = goseg
|
||
mov ax,goloc
|
||
mov userip,ax ;userip = goloc
|
||
jmp rstore ;restore user CPU state
|
||
goerr:
|
||
call bpclear ;in case any were set
|
||
jmp err
|
||
;
|
||
;
|
||
; ************************
|
||
; * *
|
||
; * h - hex math *
|
||
; * *
|
||
; ************************
|
||
;
|
||
hexmath:
|
||
call getoffset
|
||
push bx ;save first value
|
||
call getlastoffset
|
||
pop ax ;get first value
|
||
push ax ;save a copy
|
||
add ax,bx
|
||
push bx ;save second value
|
||
push ax ;save sum
|
||
call crlf
|
||
pop ax ;get sum
|
||
call printword ;print sum
|
||
call blank
|
||
pop bx ;get second value
|
||
pop ax ;get first value
|
||
sub ax,bx
|
||
call printword ;print difference
|
||
ret
|
||
;
|
||
; ****************************************
|
||
; * *
|
||
; * i - input file control block *
|
||
; * *
|
||
; ****************************************
|
||
;
|
||
ifcb:
|
||
push conptr ;save input pointer
|
||
mov di,offset fcb
|
||
call parse
|
||
cmp al,eol
|
||
jnz i0 ;only one filename
|
||
dec conptr ;to rescan eol and blank second filename in fcb
|
||
i0:
|
||
mov di,offset fcb2
|
||
call parse2 ;parse second filename
|
||
push ds
|
||
pop es ;point to DDT's ds
|
||
pop conptr ;restore input pointer
|
||
mov di,81h ;move command tail to [es]:[di]
|
||
sub cx,cx ;zero count
|
||
i1:
|
||
call conin ;get char from command tail
|
||
cmp al,eol ;end of command tail?
|
||
jz i2
|
||
stos al ;store in user's base page
|
||
inc cx ;increment count
|
||
jmps i1 ;loop until eol
|
||
i2:
|
||
mov al,0
|
||
stos al ;store 0 at end of string
|
||
mov es:.80h,cl ;store count at start of buffer
|
||
cmp mode,'E'
|
||
jnz idone ;if no file loaded with E command, we're done
|
||
mov si,offset fcb
|
||
mov di,si
|
||
mov es,userds
|
||
add cx,38 ;total bytes to move = # in command + 36 (fcb)
|
||
; +2 (0 at end of command and count byte)
|
||
rep movs al,al ;move fcb from ddt86 basepage to user's basepage
|
||
idone:
|
||
ret
|
||
ierr:
|
||
jmp err
|
||
;
|
||
; **********************************
|
||
; * *
|
||
; * l - list assembly code *
|
||
; * *
|
||
; **********************************
|
||
;
|
||
lassm:
|
||
test disempresent,0ffh
|
||
jz laserr
|
||
mov lascntsw,0 ;don't use count if end addr specified
|
||
mov numreq,0 ;ok if no entries
|
||
mov ax,type1seg
|
||
mov lasseg,ax ;default to type1 seg
|
||
mov di,offset lasloc
|
||
call getsegandoff
|
||
cmp al,eol
|
||
mov ax,lasseg
|
||
mov type1seg,ax ;update default type1 seg
|
||
jz las0
|
||
call getlastoffset ;if ',', get end address
|
||
jmps las1
|
||
las0:
|
||
mov lascntsw,1 ;disassemble fixed # of instructions
|
||
MOV AL,NLINES
|
||
MOV LASCNT,AL
|
||
mov bx,0ffffh ;set lasmax to big number
|
||
las1:
|
||
mov lasmax,bx
|
||
las2:
|
||
mov di,lasloc
|
||
cmp di,lasmax
|
||
ja lasret
|
||
push di
|
||
CALL CRLFCHK
|
||
pop di
|
||
mov es,lasseg
|
||
push es
|
||
push di ;for disem call (PL/M)
|
||
call printdword
|
||
call blank
|
||
call disem
|
||
cmp ax,lasloc
|
||
jb lasret ;stop if wrap occurred
|
||
mov lasloc, ax
|
||
test lascntsw,0ffh
|
||
jz las2
|
||
dec lascnt
|
||
jnz las2
|
||
lasret:
|
||
ret
|
||
laserr:
|
||
jmp err
|
||
;
|
||
; **************************
|
||
; * *
|
||
; * m - move block *
|
||
; * *
|
||
; **************************
|
||
;
|
||
move:
|
||
mov di,offset type2loc
|
||
call getsegandoff
|
||
call getoffset ;get end offset
|
||
mov usermax,bx
|
||
cmp al,eol
|
||
jz moverr ;need 3 arguments
|
||
sub bx,type2loc
|
||
jb moverr ;error if start > end
|
||
mov ax,type2seg
|
||
mov userseg2,ax ;default to same seg as source
|
||
mov di,offset userloc2
|
||
call getsegandoff ;get destination address
|
||
cmp al,eol
|
||
jnz moverr ;error if more than 3 arguments
|
||
mov0:
|
||
les si,dword ptr type2loc
|
||
mov al,es:[si] ;get source byte
|
||
les di,dword ptr userloc2
|
||
call setbyte ;put destination byte
|
||
inc type2loc
|
||
jz movret ;don't allow wraparound
|
||
inc userloc2
|
||
jz movret ;don't allow wraparound in destination segment
|
||
mov ax,type2loc
|
||
cmp ax,usermax ;check for done
|
||
jna mov0
|
||
movret:
|
||
ret
|
||
moverr:
|
||
jmp err
|
||
;
|
||
; *************************
|
||
; * *
|
||
; * r - read file *
|
||
; * *
|
||
; *************************
|
||
;
|
||
read:
|
||
call conin ;get first command char
|
||
cmp al,eol ;check for no input
|
||
jz rerr ;filename must be included in command
|
||
dec conptr ;to rescan first char
|
||
mov di,offset fcb
|
||
call parse
|
||
jz rerr ;no '?' or '*' allowed
|
||
cmp al,eol
|
||
jnz rerr ;no parameters after filename
|
||
mov dx,offset fcb
|
||
call open
|
||
mov mcblen,0ffffh ;largest memory request
|
||
mov dx,offset mcb
|
||
call getmaxmem ;get size of largest chuck of memory
|
||
mov dx,offset mcb
|
||
call allocabsmem ;allocate block returned from getmaxmem
|
||
call readfile ;read file into memory block
|
||
mov mcbext,0 ;only free memory at mbase
|
||
mov dx,offset mcb
|
||
call freemem ;free memory not used in read (read updated mcb)
|
||
mov ax,startreadseg
|
||
mov type2seg,ax ;set default type2 segment to file just read
|
||
mov type1seg,ax ;also type1 segment
|
||
sub ax,ax
|
||
mov disloc,ax ;display pointer offset = 0
|
||
mov lasloc,ax ;list pointer offset = 0
|
||
mov mode,'R' ;last disk input was read (not execute)
|
||
call verify
|
||
ret
|
||
rerr:
|
||
jmp err
|
||
;
|
||
; **************************
|
||
; * *
|
||
; * s - set memory *
|
||
; * *
|
||
; **************************
|
||
;
|
||
setmem:
|
||
call checkword ;check for 'SW'
|
||
mov di,offset type2loc
|
||
call getsegandoff
|
||
set0:
|
||
call crlf
|
||
les di,dword ptr type2loc
|
||
call printdword
|
||
call blank
|
||
les si,dword ptr type2loc
|
||
call print8or16
|
||
call blank
|
||
call getline
|
||
call conin
|
||
cmp al,eol
|
||
jz set2
|
||
cmp al,'.'
|
||
jz setret
|
||
dec conptr ;to rescan first character
|
||
call getlastoffset
|
||
mov ax,bx ;get new value to ax
|
||
test wmode,1
|
||
jnz set1
|
||
or bh,bh
|
||
jnz seterr ;must be < 256 if not SW
|
||
set1:
|
||
les di,dword ptr type2loc
|
||
call set8or16
|
||
set2:
|
||
mov si,offset type2loc
|
||
call inc1or2
|
||
jnb set0
|
||
setret:
|
||
ret
|
||
seterr:
|
||
jmp err
|
||
;
|
||
; ***************************************
|
||
; * *
|
||
; * t - trace program execution *
|
||
; * *
|
||
; ***************************************
|
||
;
|
||
trace:
|
||
mov traceprint,1
|
||
trace0: ;untrace enters here with traceprint = 0
|
||
call conin
|
||
cmp al,'S' ;check for TS
|
||
mov ah,1
|
||
jz tr0 ;if TS, set segflag to 1
|
||
dec ah ;else set segflag to 0, and
|
||
dec conptr ;decrement pointer to rescan character
|
||
tr0:
|
||
mov segflag,ah ;print segment registers or not
|
||
mov tracecount,1 ;default to 1 instruction trace
|
||
call getnumber
|
||
cmp al,eol
|
||
jnz traceerr ;only 1 parameter allowed
|
||
or ah,ah ;see if a number was entered
|
||
jz trace1 ;skip if no number typed
|
||
mov tracecount,bx ;store number of instructions to trace
|
||
trace1:
|
||
call xdisp ;display CPU state
|
||
jmp tracerestore ;restore user's CPU state and return
|
||
traceerr:
|
||
jmp err
|
||
;
|
||
; ******************************************
|
||
; * *
|
||
; * u - untraced program execution *
|
||
; * *
|
||
; ******************************************
|
||
;
|
||
untrace:
|
||
mov traceprint,0
|
||
jmps trace0 ;common code with trace command
|
||
;
|
||
; *********************************
|
||
; * *
|
||
; * v - display file info *
|
||
; * *
|
||
; *********************************
|
||
;
|
||
verify:
|
||
mov al,mode
|
||
cmp al,'R'
|
||
jz verifyr
|
||
cmp al,'E'
|
||
jz verifye
|
||
jmp err ;neither R nor E command done
|
||
verifyr:
|
||
call crlf
|
||
mov si,offset readm
|
||
call printm
|
||
call crlf
|
||
les di,dword ptr startreadoff
|
||
call printdword
|
||
call blank
|
||
les di,dword ptr endreadoff
|
||
call printdword
|
||
ret
|
||
;
|
||
verifye:
|
||
call crlf
|
||
mov cx,3
|
||
call tabs
|
||
mov si,offset readm
|
||
call printm ;print header
|
||
mov al,0 ;initialize count to 0
|
||
v0:
|
||
push ax ;save it
|
||
pop ax ;get count
|
||
push ax ;save it
|
||
call printseginfo ;print name, start, end of segment if non-zero
|
||
pop ax ;get count
|
||
inc al ;increment it
|
||
cmp byte ptr basepagesave+5,1 ;check for 8080 model
|
||
jz verret ;no more segments if 8080 model
|
||
cmp al,8 ;max of 8 segments described in base page
|
||
jb v0 ;done when count = 8
|
||
verret:
|
||
ret
|
||
;
|
||
; ******************************************
|
||
; * *
|
||
; * w - write memory block to disk *
|
||
; * *
|
||
; ******************************************
|
||
;
|
||
write:
|
||
mov ax,startreadseg
|
||
mov startwriteseg,ax
|
||
mov ax,startreadoff
|
||
mov startwriteoff,ax
|
||
mov ax,endreadseg
|
||
mov endwriteseg,ax
|
||
mov ax,endreadoff
|
||
mov endwriteoff,ax
|
||
call conin
|
||
cmp al,eol ;check for no parameters
|
||
jz werr ;must have a filename
|
||
dec conptr ;to rescan first char
|
||
mov di,offset fcb
|
||
call parse ;get filename
|
||
jz werr ;don't allow '?' or '*'
|
||
cmp al,eol
|
||
jnz w0 ;not end of input - must be 2 parameters
|
||
cmp mode,'R' ;see if a file was read in
|
||
jnz werr ;no file read - must have start, end addresses
|
||
jmps w1 ;continue with write
|
||
w0:
|
||
mov ax,type1seg
|
||
mov startwriteseg,ax ;set default to userds
|
||
mov di,offset startwriteoff
|
||
call getsegandoff ;get start address
|
||
cmp al,eol
|
||
jz werr ;need 2 parameters
|
||
mov ax,startwriteseg
|
||
mov endwriteseg,ax ;end defaults to start
|
||
mov di,offset endwriteoff
|
||
call getsegandoff ;get end address
|
||
cmp al,eol
|
||
jnz werr ;no more than 2 parameters
|
||
w1:
|
||
call writefile
|
||
mov dx,offset fcb
|
||
call close
|
||
ret
|
||
werr:
|
||
jmp err
|
||
;
|
||
; ***************************************
|
||
; * *
|
||
; * x - display/alter CPU state *
|
||
; * *
|
||
; ***************************************
|
||
;
|
||
xdisp: ;display CPU state
|
||
CALL SETDEFSEG ;SET TYPE1SEG, LASLOC TO CS:IP
|
||
TEST COL40,0FFH
|
||
JNZ XD40
|
||
call printregheader
|
||
xnohdr: ;entry point to display CPU state without header
|
||
TEST COL40,0FFH
|
||
JNZ XNH40
|
||
call crlf
|
||
call printflags
|
||
call blank
|
||
call printregs
|
||
call printinstr ;disassemble instruction at [cs:ip]
|
||
ret
|
||
;
|
||
XD40:
|
||
CALL PREGHDR1
|
||
MOV AL,1
|
||
JMPS XD0
|
||
XNH40:
|
||
MOV AL,0
|
||
XD0:
|
||
PUSH AX ;SAVE HEADER/NO HEADER FLAG
|
||
CALL CRLF
|
||
CALL PRINTFLAGS
|
||
CALL BLANK
|
||
CALL PREG1
|
||
CALL CRLF
|
||
POP AX
|
||
DEC AL
|
||
JNZ XD1
|
||
CALL PREGHDR2
|
||
CALL CRLF
|
||
XD1:
|
||
CALL PREG2
|
||
CALL PRINTINSTR
|
||
RET
|
||
xcom:
|
||
mov segflag,1 ;display seg reg's in x command
|
||
call conin
|
||
cmp al,eol ;check for command by itself
|
||
jz xdisp ;if so, simply display CPU state
|
||
mov xtemp,al ;else save char
|
||
call conin
|
||
cmp al,eol ;check for single character after X
|
||
jz xflag ;if so, must be a flag name
|
||
mov ah,xtemp ;else it's a reg name
|
||
or al,80h ;since names are declared that way
|
||
xchg al,ah ;since that's how it is in memory
|
||
call chkreg ;check for valid reg name + store number in regnum
|
||
call conin
|
||
cmp al,eol
|
||
jnz xerr ;eol must follow reg name
|
||
x0:
|
||
call crlf
|
||
mov cx,regnum
|
||
call printregname
|
||
call blank
|
||
mov cx,regnum
|
||
call printregval
|
||
call blank
|
||
call getline
|
||
call conin
|
||
cmp al,'.'
|
||
jz xret ;done when '.' entered
|
||
dec conptr ;else rescan character
|
||
call getnumber
|
||
cmp al,eol
|
||
jnz xerr ;eol must follow number
|
||
or ah,ah ;see if non-blank entry
|
||
jz xnext ;if blank, go to next reg
|
||
mov cx,regnum
|
||
mov ax,bx ;get new value
|
||
cmp cl,8 ;are we updating cs?
|
||
jnz x1
|
||
mov type1seg,ax ;if so, update default type1 segment
|
||
x1:
|
||
cmp cl,9 ;are we updating ds?
|
||
jnz x2
|
||
mov type2seg,ax ;if so, update default type2 segment
|
||
x2:
|
||
call setreg
|
||
xnext:
|
||
inc regnum
|
||
cmp regnum,totreg
|
||
jb x0
|
||
ret
|
||
xerr:
|
||
jmp err
|
||
;
|
||
xflag:
|
||
mov al,xtemp ;get flag name
|
||
call checkflag ;check for valid flag name
|
||
call crlf
|
||
mov cx,regnum ;restore flag number
|
||
call printflagname
|
||
call blank
|
||
mov cx,regnum
|
||
call printflagval
|
||
call blank
|
||
call getline
|
||
call getnumber
|
||
cmp al,eol
|
||
jnz xerr ;eol must follow number
|
||
or ah,ah ;see if non-blank entry
|
||
jz xret ;if blank, done
|
||
cmp bx,1
|
||
ja xerr ;flag value must be 0 or 1
|
||
mov cx,regnum
|
||
call setflag
|
||
xret:
|
||
ret
|
||
;
|
||
eject
|
||
; *********************************
|
||
; * *
|
||
; * d a t a a r e a *
|
||
; * *
|
||
; *********************************
|
||
;
|
||
; user regs must be in cseg, others may be in dseg
|
||
;
|
||
userax dw 0
|
||
userbx dw 0
|
||
usercx dw 0
|
||
userdx dw 0
|
||
usersp dw 0
|
||
userbp dw 0
|
||
usersi dw 0
|
||
userdi dw 0
|
||
usercs dw 0
|
||
userds dw 0
|
||
userss dw 0
|
||
useres dw 0
|
||
userip dw 0
|
||
userfl dw 0
|
||
userreg equ userax
|
||
;
|
||
savess dw 0 ;temp holder for sp
|
||
savesp dw 0 ;temp holder for sp
|
||
;
|
||
breakfl rs 1 ;break/single step flag (must be in CS)
|
||
;
|
||
endcs equ $
|
||
;
|
||
dseg
|
||
org offset endcs
|
||
;
|
||
; CCP STACK LOCATION
|
||
;
|
||
CCPSS DW 0
|
||
CCPSP DW 0
|
||
;
|
||
; console buffer declarations
|
||
;
|
||
conbuffmax equ 64
|
||
conbuffhdr db conbuffmax
|
||
conbuffcnt db 0
|
||
conbuff rs conbuffmax+1 ;leave room for eol
|
||
conptr dw 0
|
||
;
|
||
; a command declarations
|
||
;
|
||
assempresent db 1 ;assembler in memory flag
|
||
asmspsav rw 1 ;temporary save for stack pointer
|
||
;
|
||
; d command declarations
|
||
;
|
||
disloc dw 0 ;offset for display
|
||
disseg dw 0 ;segment for display
|
||
dismax rw 1 ;end offset of display
|
||
tdisp rw 1 ;temporary storage for disloc
|
||
LINEMAX DB 0 ;# OF BYTES PER LINE
|
||
ND80 DB 16 ;16 BYTES PER LINE IN 80 COL MODE
|
||
ND40 DB 6 ;6 BYTES PER LINE IN 40 COL MODE
|
||
NDW40 DB 8 ;8 BYTES (4 WORDS) FOR DW IN 40 COL MODE
|
||
NLINES DB 12 ;DEFAULT NUMBER OF LINES FOR L, D COMMANDS
|
||
;
|
||
; g command declarations
|
||
;
|
||
goloc dw 0
|
||
goseg dw 0
|
||
vectorsave rs 12 ;save area for bytes at 0004h to 000fh
|
||
bpcnt db 0 ;breakpoint count
|
||
brk1loc dw 0
|
||
brk1seg dw 0
|
||
brk1byt db 0
|
||
brk2loc dw 0
|
||
brk2seg dw 0
|
||
brk2byt db 0
|
||
;
|
||
; l command declarations
|
||
;
|
||
lasloc dw 0
|
||
lasseg dw 0
|
||
lasmax dw 0
|
||
lascntsw rb 1 ;# instructions specified or not
|
||
lascnt rb 1 ;number of instructions to disassemble
|
||
disempresent db 1 ;disassembler in memory flag
|
||
;
|
||
; r command declarations
|
||
;
|
||
startreadoff rw 1 ;offset where file read starts
|
||
startreadseg rw 1 ;segment where file read starts
|
||
endreadoff rw 1 ;offset where file read ends
|
||
endreadseg rw 1 ;segment where file read ends
|
||
dmaoff rw 1 ;offset of 20-bit dma address
|
||
dmaseg rw 1 ;segment of 20-bit dma address
|
||
;
|
||
; t/u command declarations
|
||
;
|
||
tracecount rw 1 ;number of instructions to trace
|
||
traceprint rb 1 ;display CPU state on each step flag
|
||
skipbdos db 0 ;set when trace suspended during BDOS call
|
||
USERIFOFF DB 0 ;SET WHEN DDT86 MUST REENABLE USER IF
|
||
;
|
||
; w command declarations
|
||
;
|
||
startwriteoff rw 1 ;offset where file write starts
|
||
startwriteseg rw 1 ;segment where file write starts
|
||
endwriteoff rw 1 ;offset where file write ends
|
||
endwriteseg rw 1 ;segment where file write ends
|
||
;
|
||
; x command declarations
|
||
;
|
||
NREG DB 0 ;CURRENT NUMBER OF REGISTER NAMES TO DISPLAY
|
||
;(MAY DIFFER FOR 40 COLUMN MODE)
|
||
TOTREG EQU 13 ;TOTAL NUMBER OF REGISTER NAMES
|
||
nflag equ 9 ;number of flag names
|
||
segflag db 1 ;print segment register flag
|
||
regnum rw 1 ;temp for reg/flag number
|
||
xtemp rb 1 ;temp for first char of reg name
|
||
;
|
||
type1loc dw 0 ;offset for type 1 commands
|
||
type1seg dw 0 ;segment for type 1 commands
|
||
type2loc dw 0 ;offset for type 2 commands
|
||
type2seg dw 0 ;segment for type 2 commands
|
||
usermax rw 1
|
||
userloc2 rw 1
|
||
userseg2 rw 1
|
||
;
|
||
; memory control block declarations
|
||
;
|
||
mcb rs 0 ;used in reading/writing file
|
||
mcbbase dw 0 ;segment of memory block
|
||
mcblen dw 0 ;length of memory block
|
||
mcbext db 0 ;returned value from bdos memory functions
|
||
;
|
||
sysif rb 1 ;system interrupt flag
|
||
numreq rb 1 ;number required or optional
|
||
wmode rb 1 ;set for DW, FW and SW commands
|
||
mode db 'I' ;last disk access with 'R' or 'E' command
|
||
savevecflag db 0 ;save/restore bp and ss vectors, or not
|
||
COL40 DB 0 ;PATCHED TO 1 FOR 40 COLUMN CONSOLE
|
||
ERRMODE DB 0 ;SET IF BDOS RETURN ERR MODE SET (V3.0)
|
||
;
|
||
basepagesave rb 48 ;copy of user's base page
|
||
;
|
||
; parsing declarations
|
||
;
|
||
delims db ' ', '=', '.', ',', ':', ';', '[', ']', '<', '>', eol
|
||
ndelims equ offset $ - offset delims
|
||
lastchar db 0
|
||
fcbadr dw 0 ;temp storage for fcb address
|
||
;
|
||
rs stsize ;stack size
|
||
stackp rs 0 ;top of stack
|
||
;
|
||
if debug
|
||
;
|
||
biosentryoff dw 0a00h ;empty part of ccp (hopefully)
|
||
biosentryseg dw 0 ;same as bdos segment
|
||
;
|
||
endif
|
||
;
|
||
end
|
||
|