1 TITLE PART2 DEBUGGER COMMANDS
3 ; Routines to perform debugger commands except ASSEMble and UASSEMble
12 CODE SEGMENT PUBLIC BYTE 'CODE'
15 CONST
SEGMENT PUBLIC BYTE
17 EXTRN NOTFND
:BYTE,NOROOM
:BYTE,DRVLET
:BYTE,NOSPACE
:BYTE,NAMBAD
:BYTE
18 EXTRN TOOBIG
:BYTE,ERRMES
:BYTE
19 EXTRN EXEBAD
:BYTE,HEXERR
:BYTE,EXEWRT
:BYTE,HEXWRT
:BYTE
20 EXTRN EXECEMES
:BYTE,WRTMES1
:BYTE,WRTMES2
:BYTE,ACCMES
:BYTE
22 EXTRN FLAGTAB
:WORD,EXEC_BLOCK
:BYTE,COM_LINE
:DWORD,COM_FCB1
:DWORD
23 EXTRN COM_FCB2
:DWORD,COM_SSSP
:DWORD,COM_CSIP
:DWORD,RETSAVE
:WORD
24 EXTRN NEWEXEC
:BYTE,HEADSAVE
:WORD
25 EXTRN REGTAB
:BYTE,TOTREG
:BYTE,NOREGL
:BYTE
26 EXTRN USER_PROC_PDB
:WORD,STACK:BYTE,RSTACK
:WORD,AXSAVE
:WORD
27 EXTRN BXSAVE
:WORD,DSSAVE
:WORD,ESSAVE
:WORD,CSSAVE
:WORD,IPSAVE
:WORD
28 EXTRN SSSAVE
:WORD,CXSAVE
:WORD,SPSAVE
:WORD,FSAVE:WORD
29 EXTRN SREG
:BYTE,SEGTAB
:WORD,REGDIF
:WORD,RDFLG
:BYTE
33 DATA SEGMENT PUBLIC BYTE
35 EXTRN DEFDUMP
:BYTE,TRANSADD
:DWORD,INDEX
:WORD,BUFFER
:BYTE
36 EXTRN ASMADD
:BYTE,DISADD
:BYTE,NSEG
:WORD,BPTAB
:BYTE
37 EXTRN BRKCNT
:WORD,TCOUNT
:WORD,SWITCHAR
:BYTE,XNXCMD
:BYTE,XNXOPT
:BYTE
38 EXTRN AWORD
:BYTE,EXTPTR
:WORD,HANDLE
:WORD,PARSERR
:BYTE
42 DG GROUP
CODE,CONST
,DATA
45 CODE SEGMENT PUBLIC BYTE 'CODE'
46 ASSUME
CS:DG
,DS:DG
,ES:DG
,SS:DG
48 PUBLIC DEFIO
,SKIP_FILE
,PREPNAME
,DEBUG_FOUND
49 PUBLIC REG
,COMPARE
,GO
,INPUT
,LOAD
50 PUBLIC NAME
,OUTPUT
,TRACE
,ZTRACE
,DWRITE
55 EXTRN GETHEX
:NEAR,GETEOL
:NEAR
56 EXTRN CRLF
:NEAR,BLANK
:NEAR,OUT:NEAR
57 EXTRN OUTSI
:NEAR,OUTDI
:NEAR,INBUF
:NEAR,SCANB
:NEAR,SCANP
:NEAR
58 EXTRN RPRBUF
:NEAR,HEX
:NEAR,OUT16
:NEAR,DIGIT
:NEAR
59 EXTRN COMMAND
:NEAR,DISASLN
:NEAR,SET_TERMINATE_VECTOR
:NEAR
60 EXTRN RESTART
:NEAR,DABORT
:NEAR,TERMINATE
:NEAR,DRVERR
:NEAR
61 EXTRN FIND_DEBUG
:NEAR,NMIInt
:NEAR,NMIIntEnd
:NEAR
62 EXTRN HEXCHK
:NEAR,GETHEX1
:NEAR,PRINT
:NEAR,DSRANGE
:NEAR
63 EXTRN ADDRESS
:NEAR,HEXIN
:NEAR,PERROR
:NEAR
68 MOV SI,OFFSET DG
:REGTAB
69 MOV BX,OFFSET DG
:AXSAVE
70 MOV BYTE PTR TOTREG
,13
87 MOV WORD PTR [DISADD
],AX
90 MOV WORD PTR [DISADD
+2],AX
106 MOV AX,WORD PTR [BX+SREG
]
122 TEST BYTE PTR [AWORD
],-1
134 ; Perform register dump if no parameters or set register if a
135 ; register designation is a parameter.
149 MOV DI,OFFSET DG
:REGTAB
183 MOV AX,5200H
+"B" ; BR ERROR
201 MOV DI,OFFSET DG
:FLAGTAB
222 LODS CS:WORD PTR [SI]
237 MOV AX,4600H
+"D" ; DF ERROR
244 MOV SI,OFFSET DG
:ERRMES
250 MOV AX,4600H
+"B" ; BF ERROR
253 MOV SI,OFFSET DG
:FLAGTAB
257 LODS CS:WORD PTR [SI]
272 ; Input from the specified port and display result
275 MOV CX,4 ; Port may have 4 digits
276 CALL GETHEX
; Get port number in DX
278 IN AL,DX ; Variable port input
279 CALL HEX
; And display
282 ; Output a value to specified port.
285 MOV CX,4 ; Port may have 4 digits
286 CALL GETHEX
; Get port number
287 PUSH DX ; Save while we get data
288 MOV CX,2 ; Byte output only
289 CALL GETHEX
; Get data to output
291 XCHG AX,DX ; Output data in AL
293 OUT DX,AL ; Variable port output
300 CALL ADDRESS
; Same segment
308 CALL COMP
; Do one less than total
309 INC CX ; CX=1 (do last one)
313 ; Compare error. Print address, value; value, address.
335 ; just like trace except skips OVER next INT or CALL.
336 CALL SETADD
; get potential starting point
337 CALL GETEOL
; check for end of line
338 MOV [TCOUNT
],1 ; only a single go at it
339 MOV ES,[CSSAVE
] ; point to instruction to execute
340 MOV DI,[IPSAVE
] ; include offset in segment
341 XOR DX,DX ; where to place breakpoint
342 MOV AL,ES:[DI] ; get the opcode
343 CMP AL,11101000B ; direct intra call
344 JZ ZTrace3
; yes, 3 bytes
345 CMP AL,10011010B ; direct inter call
346 JZ ZTrace5
; yes, 5 bytes
347 CMP AL,11111111B ; indirect?
348 JZ ZTraceModRM
; yes, go figure length
349 CMP AL,11001100B ; short interrupt?
350 JZ ZTrace1
; yes, 1 byte
351 CMP AL,11001101B ; long interrupt?
352 JZ ZTrace2
; yes, 2 bytes
353 CMP AL,11100010B ; loop
355 CMP AL,11100001B ; loopz/loope
357 CMP AL,11100000B ; loopnz/loopne
359 AND AL,11111110B ; check for rep
360 CMP AL,11110010B ; perhaps?
361 JNZ Step
; can't do anything special, step
362 MOV AL,ES:[DI+1] ; next instruction
363 AND AL,11111110B ; ignore w bit
364 CMP AL,10100100B ; MOVS
365 JZ ZTrace2
; two byte
366 CMP AL,10100110B ; CMPS
367 JZ ZTrace2
; two byte
368 CMP AL,10101110B ; SCAS
369 JZ ZTrace2
; two byte
370 CMP AL,10101100B ; LODS
371 JZ ZTrace2
; two byte
372 CMP AL,10101010B ; STOS
373 JZ ZTrace2
; two byte
374 JMP Step
; bogus, do single step
377 MOV AL,ES:[DI+1] ; get next byte
378 AND AL,11111000B ; get mod and type
379 CMP AL,01010000B ; indirect intra 8 bit offset?
380 JZ ZTrace3
; yes, three byte whammy
381 CMP AL,01011000B ; indirect inter 8 bit offset
382 JZ ZTrace3
; yes, three byte guy
383 CMP AL,10010000B ; indirect intra 16 bit offset?
384 JZ ZTrace4
; four byte offset
385 CMP AL,10011000B ; indirect inter 16 bit offset?
386 JZ ZTrace4
; four bytes
387 JMP Step
; can't figger out what this is!
393 ADD DI,DX ; offset to breakpoint instruction
394 MOV WORD PTR [BPTab
],DI ; save offset
395 MOV WORD PTR [BPTab
+2],ES ; save segment
396 MOV AL,ES:[DI] ; get next opcode byte
397 MOV BYTE PTR [BPTab
+4],AL ; save it
398 MOV BYTE PTR ES:[DI],0CCh ; break point it
399 MOV [BrkCnt
],1 ; only this breakpoint
400 JMP DExit
; start the operation!
403 ; Trace 1 instruction or the number of instruction specified
404 ; by the parameter using 8086 trace mode. Registers are all
405 ; set according to values in save area
420 OR BYTE PTR [FSAVE+1],1
423 MOV BX,[USER_PROC_PDB
]
424 MOV AH,SET_CURRENT_PDB
430 MOV WORD PTR DS:[12],OFFSET DG
:BREAKFIX
; Set vector 3--breakpoint instruction
431 MOV WORD PTR DS:[14],CS
432 MOV WORD PTR DS:[4],OFFSET DG
:REENTER
; Set vector 1--Single step
433 MOV WORD PTR DS:[6],CS
437 MOV WORD PTR DS:[8
CH],OFFSET DG
:CONTC
; Set vector 23H (CTRL-C)
438 MOV WORD PTR DS:[8EH
],CS
442 MOV SP,OFFSET DG
:STACK
465 ; Re-entry point from CTRL-C. Top of stack has address in 86-DOS for
466 ; continuing, so we must pop that off.
470 JMP SHORT ReEnterReal
472 ; Re-entry point from breakpoint. Need to decrement instruction
473 ; pointer so it points to location where breakpoint actually
479 DEC WORD PTR [BP].OldIP
483 ; Re-entry point from trace mode or interrupt during
484 ; execution. All registers are saved so they can be
485 ; displayed or modified.
487 Interrupt_Frame
STRUC
499 MOV BP,SP ; get a frame to address from
502 CMP AX,[BP].OldCS
; Did we interrupt ourselves?
503 JNZ GoReEnter
; no, go reenter
505 CMP AX,OFFSET DG
:NMIInt
; interrupt below NMI interrupt?
506 JB GoReEnter
; yes, go reenter
507 CMP [BP].OLDIP
,OFFSET DG
:NMIIntEnd
508 JAE GoReEnter
; interrupt above NMI interrupt?
509 POP AX ; restore state
511 SUB SP,6 ; switch TRACE and NMI stack frames
513 MOV BP,SP ; set up frame
514 PUSH AX ; get temp variable
515 MOV AX,[BP].OlderIP
; get NMI Vector
516 MOV [BP].OldIP
,AX ; stuff in new NMI vector
517 MOV AX,[BP].OlderCS
; get NMI Vector
518 MOV [BP].OldCS
,AX ; stuff in new NMI vector
519 MOV AX,[BP].OlderF
; get NMI Vector
520 AND AH,0FEh ; turn off Trace if present
521 MOV [BP].OldF
,AX ; stuff in new NMI vector
523 MOV [BP].OlderIP
,OFFSET DG
:ReEnter
; offset of routine
524 MOV [BP].OlderCS
,CS ; and CS
532 MOV CS:[SPSAVE
+SEGDIF
],SP
533 MOV CS:[SSSAVE
+SEGDIF
],SS
536 MOV SP,OFFSET DG
:RSTACK
555 AND AH,0FEH ; turn off trace mode bit
562 MOV SP,OFFSET DG
:STACK
568 MOV WORD PTR DS:[8
CH],OFFSET DG
:DABORT
; Set Ctrl-C vector
569 MOV WORD PTR DS:[8EH
],CS
576 MOV AH,GET_CURRENT_PDB
578 MOV [USER_PROC_PDB
],BX
580 MOV AH,SET_CURRENT_PDB
587 MOV SI,OFFSET DG
:BPTAB
592 LES DI,DWORD PTR [SI]
605 CMP BYTE PTR [SI],"="
613 ; Jump to program, setting up registers according to the
614 ; save area. up to 10 breakpoint addresses may be specified.
619 MOV DI,OFFSET DG
:BPTAB
625 MOV [DI],DX ; Save offset
626 MOV [DI+2],AX ; Save segment
627 ADD DI,5 ; Leave a little room
631 MOV AX,5000H
+"B" ; BP ERROR
637 MOV DI,OFFSET DG
:BPTAB
640 LDS SI,ES:DWORD PTR [DI]
643 MOV BYTE PTR [SI-1],0CCH
653 MOV [SWITCHAR
],DL ; GET THE CURRENT SWITCH CHARACTER
675 MOV ES:(BYTE PTR [80H
]),AL
678 MOV AX,(PARSE_FILE_DESCRIPTOR
SHL 8) OR 01H
680 MOV BYTE PTR [AXSAVE
],AL ; Indicate analysis of first parm
683 MOV AX,(PARSE_FILE_DESCRIPTOR
SHL 8) OR 01H
685 MOV BYTE PTR [AXSAVE
+1],AL ; Indicate analysis of second parm
689 ; OPENS A XENIX PATHNAME SPECIFIED IN THE UNFORMATTED PARAMETERS
690 ; VARIABLE [XNXCMD] SPECIFIES WHICH COMMAND TO OPEN IT WITH
692 ; VARIABLE [HANDLE] CONTAINS THE HANDLE
693 ; VARIABLE [EXTPTR] POINTS TO THE FILES EXTENSION
696 MOV BYTE PTR [XNXCMD
],UNLINK
700 MOV BYTE PTR [XNXCMD
],0
704 MOV BYTE PTR [XNXCMD
],EXEC
705 MOV BYTE PTR [XNXOPT
],1
709 MOV BYTE PTR [XNXCMD
],OPEN
710 MOV BYTE PTR [XNXOPT
],2 ; Try read write
713 MOV BYTE PTR [XNXCMD
],OPEN
714 MOV BYTE PTR [XNXOPT
],0 ; Try read only
718 MOV BYTE PTR [XNXCMD
],CREAT
729 MOV [EXTPTR
],AX ; INITIALIZE POINTER TO EXTENSIONS
732 MOV [SWITCHAR
],DL ; GET THE CURRENT SWITCH CHARACTER
737 CALL DELIM2
; END OF LINE?
739 CALL DELIM1
; SKIP LEADING DELIMITERS
742 MOV DX,SI ; SAVE POINTER TO BEGINNING
744 OPEN2: CMP AL,"." ; LAST CHAR A "."?
746 MOV [EXTPTR
],SI ; SAVE POINTER TO THE EXTENSION
748 CALL DELIM1
; LOOK FOR END OF PATHNAME
753 OPEN4: DEC SI ; POINT BACK TO LAST CHAR
754 PUSH [SI] ; SAVE TERMINATION CHAR
755 MOV BYTE PTR [SI],0 ; NULL TERMINATE THE STRING
758 MOV AH,[XNXCMD
] ; OPEN OR CREATE FILE
761 MOV BX,OFFSET DG
:EXEC_BLOCK
764 MOV CS:[HANDLE
],AX ; SAVE ERROR CODE OR HANDLE
789 DELIM1: CMP AL," " ; SKIP THESE GUYS
800 DELIM2: CMP AL,[SWITCHAR
] ; STOP ON THESE GUYS
807 MOV AL,BYTE PTR AXSAVE
813 MOV SI,FCB
; DS:SI points to user FCB
814 MOV DI,SI ; ES:DI points to DEBUG FCB
820 MOV DX,OFFSET DG
:NAMBAD
824 CMP BYTE PTR [PARSERR
],-1 ; Invalid drive specification?
828 CMP WORD PTR DS:[BX],"EH" ; "HE"
830 CMP BYTE PTR DS:[BX+2],"X"
836 CMP WORD PTR DS:[BX],"XE" ; "EX"
838 CMP BYTE PTR DS:[BX+2],"E"
843 MOV BYTE PTR [RDFLG
],READ
847 MOV BYTE PTR [RDFLG
],WRITE
857 PRMIO: PUSH AX ; Save segment
858 MOV BX,DX ; Put displacement in proper register
860 CALL GETHEX
; Drive number must be 1 digit
863 CALL GETHEX
; Logical record number
866 CALL GETHEX
; Number of records
869 POP DX ; Logical record number
870 POP AX ; Drive number
871 CBW ; Turn off verify after write
872 MOV BYTE PTR DRVLET
,AL ; Save drive in case of error
884 POP DS ; Segment of transfer
886 CMP CS:BYTE PTR [RDFLG
],WRITE
888 INT 25H
; Primitive disk read
892 INT 26H
; Primitive disk write
902 MOV AX,[CSSAVE
] ; Default segment
903 MOV DX,100H
; Default file I/O offset
906 XOR DX,DX ; If HEX file, default OFFSET is zero
910 ; AX and DX have segment and offset of transfer, respectively
916 CMP BYTE PTR [RDFLG
],READ
918 MOV DX,OFFSET DG
:EXEWRT
919 JMP RESTART
; Can't write .EXE files
922 CMP BYTE PTR [RDFLG
],WRITE
924 CMP WORD PTR DS:[BX],4F00H
+ "C" ; "CO"
926 CMP BYTE PTR DS:[BX+2],"M"
935 OAF: CALL OPEN_A_FILE
937 MOV AX,exec_file_not_found
946 CALL IFEXE
; SUBTRACT 512 BYTES FOR EXE
947 JNZ BIN2
; FILE LENGTH BECAUSE OF
948 SUB AX,512 ; THE HEADER
949 BIN2: MOV [BXSAVE
],DX ; SET UP FILE SIZE IN DX:AX
956 MOV DX,OFFSET DG
:TOOBIG
957 MOV AH,STD_CON_STRING_OUTPUT
961 WRTFILEJ: JMP WRTFILE
967 CMP BYTE PTR [RDFLG
],WRITE
972 MOV AX,(LSEEK
SHL 8) OR 2
975 INT 21H
; GET SIZE OF FILE
977 MOV DI,AX ; SIZE TO SI:DI
978 MOV AX,(LSEEK
SHL 8) OR 0
981 INT 21H
; RESET POINTER BACK TO BEGINNING
985 PUSH AX ; TRANS ADDR TO BX:AX
989 ADD BX,AX ; Start of transfer rounded up to seg
991 MOV AX,DI ; DX:AX is size
997 NOREM: ; AX is number of paras in transfer
998 ADD AX,BX ; AX is first seg that need not exist
999 CMP AX,CS:[PDB_block_len
]
1007 ; AX:DX is disk transfer address (segment:offset)
1008 ; SI:DI is length (32-bit number)
1011 MOV BX,DX ; Make a copy of the offset
1012 AND DX,000FH ; Establish the offset in 0H-FH range
1014 SHR BX,CL ; Shift offset and
1015 ADD AX,BX ; Add to segment register to get new Seg:offset
1017 PUSH DX ; Save AX,DX register pair
1018 MOV WORD PTR [TRANSADD
],DX
1019 MOV WORD PTR [TRANSADD
+2],AX
1020 MOV CX,0FFF0H ; Keep request in segment
1021 OR SI,SI ; Need > 64K?
1023 MOV CX,DI ; Limit to amount requested
1030 INT 21H
; Perform read or write
1034 CMP BYTE PTR [RDFLG
],WRITE
1040 POP DX ; READ OR WRITE BOMBED OUT
1046 SUB DI,CX ; Request minus amount transferred
1047 SBB SI,0 ; Ripple carry
1048 OR CX,CX ; End-of-file?
1049 POP DX ; Restore DMA address
1052 ADD DX,CX ; Bump DMA address by transfer length
1054 OR BX,DI ; Finished with request
1056 RET8: CLC ; End-of-file not reached
1060 MOV DX,OFFSET DG
:NOTFND
1065 CALL CREATE_A_FILE
; Create file we want to write to
1066 MOV DX,OFFSET DG
:NOROOM
; Creation error - report error
1068 MOV SI,BXSAVE
; Get high order number of bytes to transfer
1070 JLE WRTSIZE
; Is bx less than or equal to FH
1071 XOR SI,SI ; Ignore BX if greater than FH - set to zero
1073 MOV DX,OFFSET DG
:WRTMES1
; Print number bytes we are writing
1082 CALL OUT16
; Amount to write is SI:DI
1083 MOV DX,OFFSET DG
:WRTMES2
1091 MOV DX,OFFSET DG
:NOSPACE
1103 POP [RETSAVE
] ; Suck up return addr
1104 INC BYTE PTR [NEWEXEC
]
1105 MOV BX,[USER_PROC_PDB
]
1114 MOV BYTE PTR [NEWEXEC
],0
1116 PUSH [RETSAVE
] ; Get the return address back
1123 ADD BX,10H
; RESERVE HEADER
1127 MOV WORD PTR [COM_LINE
+2],AX
1128 MOV WORD PTR [COM_FCB1
+2],AX
1129 MOV WORD PTR [COM_FCB2
+2],AX
1133 CALL SET_TERMINATE_VECTOR
; Reset int 22
1134 MOV AH,GET_CURRENT_PDB
1136 MOV [USER_PROC_PDB
],BX
1140 MOV WORD PTR ES:[PDB_exit
],OFFSET DG
:TERMINATE
1141 MOV WORD PTR ES:[PDB_exit
+2],DS
1145 MOV WORD PTR [DISADD
+2],ES
1146 MOV WORD PTR [DISADD
],DI
1147 MOV WORD PTR [ASMADD
+2],ES
1148 MOV WORD PTR [ASMADD
],DI
1149 MOV WORD PTR [DEFDUMP
+2],ES
1150 MOV WORD PTR [DEFDUMP
],DI
1152 MOV AH,SET_CURRENT_PDB
1164 MOV DX,OFFSET DG
:NOTFND
1165 CMP AX,exec_file_not_found
1167 MOV DX,OFFSET DG
:ACCMES
1168 CMP AX,error_access_denied
1170 MOV DX,OFFSET DG
:TOOBIG
1171 CMP AX,exec_not_enough_memory
1173 MOV DX,OFFSET DG
:EXEBAD
1174 CMP AX,exec_bad_format
1176 MOV DX,OFFSET DG
:EXECEMES
1178 MOV AH,STD_CON_STRING_OUTPUT
1184 MOV DX,OFFSET DG
:HEXWRT
1185 CMP BYTE PTR [RDFLG
],WRITE
1191 MOV DX,OFFSET DG
:NOTFND
1196 MOV SI,OFFSET DG
:(BUFFER
+BUFSIZ
) ; Flag input buffer as empty
1199 CMP AL,":" ; Search for : to start line
1201 CALL GETBYT
; Get byte count
1205 CALL GETBYT
; Get high byte of load address
1207 CALL GETBYT
; Get low byte of load address
1209 ADD BX,[INDEX
] ; Add in offset
1211 CALL GETBYT
; Throw away type byte
1213 CALL GETBYT
; Get data byte
1215 CMP DI,BP ; Check if this is the largest address so far
1217 MOV BP,DI ; Save new largest
1223 CMP SI,OFFSET DG
:(BUFFER
+BUFSIZ
)
1225 MOV DX,OFFSET DG
:BUFFER
1252 MOV DX,OFFSET DG
:HEXERR