Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1058 lines
24 KiB

PAGE 60,132
TITLE DEBCOM1.ASM - PART1 DEBUGGER COMMANDS PC DOS
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;======================= START OF SPECIFICATIONS =========================
;
; MODULE NAME: DECOM1.asm
;
; DESCRIPTIVE NAME: DEBUGGING TOOL
;
; FUNCTION: PROVIDES USERS WITH A TOOL FOR DEBUGGING PROGRAMS.
;
; ENTRY POINT: ANY CALLED ROUTINE
;
; INPUT: NA
;
; EXIT NORMAL: NA
;
; EXIT ERROR: NA
;
; INTERNAL REFERENCES:
;
; EXTERNAL REFERENCES:
;
; ROUTINE: DEBCOM2 - CONTAINS ROUTINES CALLED BY DEBUG
; DEBCOM3 - CONTAINS ROUTINES CALLED BY DEBUG
; DEBASM - CONTAINS ROUTINES CALLED BY DEBUG
; DEBUASM - CONTAINS ROUTINES CALLED BY DEBUG
; DEBMES - CONTAINS ROUTINES CALLED BY DEBUG
;
; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS.
; LINK DEBUG+DEBCOM1+DEBCOM2+DEBCOM3+DEBASM+DEBUASM+DEBERR+
; DEBCONST+DEBDATA+DEBMES
;
; REVISION HISTORY:
;
; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING:
;
; - IMPLEMENT DBCS HANDLING DMS:6/17/87
; - IMPLEMENT MESSAGE RETRIEVER DMS:6/17/87
; - IMPLEMENT > 32MB SUPPORT DMS:6/17/87
;
; COPYRIGHT: "MS DOS DEBUG UTILITY"
; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft"
; "LICENSED MATERIAL - PROPERTY OF Microsoft "
;
;======================= END OF SPECIFICATIONS ===========================
; Routines to perform debugger commands except ASSEMble and UASSEMble
IF1
;%out COMPONENT=DEBUG, MODULE=DEBCOM1
ENDIF
.XLIST
.XCREF
include syscall.inc ; cas -- missing equates
include version.inc ; cas -- missing equates
INCLUDE DOSSYM.INC
INCLUDE debug.inc
.CREF
.LIST
CODE SEGMENT PUBLIC BYTE
CODE ENDS
CONST SEGMENT PUBLIC BYTE
EXTRN SYNERR_PTR:BYTE
EXTRN DISPB:WORD,DSIZ:BYTE,DSSAVE:WORD
IF SYSVER
EXTRN CIN:DWORD,PFLAG:BYTE
ENDIF
CONST ENDS
CSTACK SEGMENT STACK
CSTACK ENDS
DATA SEGMENT PUBLIC BYTE
EXTRN DEFLEN:WORD,BYTEBUF:BYTE,DEFDUMP:BYTE
EXTRN ARG_BUF:BYTE,ARG_BUF_PTR:BYTE
EXTRN ONE_CHAR_BUF:BYTE,ONE_CHAR_BUF_PTR:WORD
DATA ENDS
DG GROUP CODE,CONST,CSTACK,DATA
CODE SEGMENT PUBLIC BYTE
ASSUME CS:DG,DS:DG,ES:DG,SS:DG
PUBLIC HEXCHK,GETHEX1,PRINT,DSRANGE,ADDRESS,HEXIN,PERROR
PUBLIC GETHEX,GET_ADDRESS,GETEOL,GETHX,PERR
PUBLIC PERR,MOVE,DUMP,ENTERDATA,FILL,SEARCH,DEFAULT
ifdef JAPAN
public SETDUMPMODE
extrn test_lead:near
endif
IF SYSVER
PUBLIC IN
EXTRN DISPREG:NEAR,DEVIOCALL:NEAR
ENDIF
EXTRN CRLF:NEAR,OUTDI:NEAR,OUTSI:NEAR,SCANP:NEAR
EXTRN SCANB:NEAR,BLANK:NEAR,TAB:NEAR,COMMAND:NEAR
EXTRN HEX:NEAR,BACKUP:NEAR
EXTRN PRINTF_CRLF:NEAR,HEX_ADDRESS_ONLY:NEAR,HEX_ADDRESS_STR:NEAR
EXTRN STD_PRINTF:NEAR
DEBCOM1:
; RANGE - Looks for parameters defining an address range.
; The first parameter is the starting address. The second parameter
; may specify the ending address, or it may be preceded by
; "L" and specify a length (4 digits max), or it may be
; omitted and a length of 128 bytes is assumed. Returns with
; segment in AX, displacement in DX, and length in CX.
DSRANGE:
MOV BP,[DSSAVE] ; Set default segment to DS
MOV [DEFLEN],128 ; And default length to 128 bytes
RANGE:
CALL ADDRESS
PUSH AX ; Save segment
PUSH DX ; Save offset
CALL SCANP ; Get to next parameter
MOV AL,[SI]
CMP AL,UPPER_L ; Length indicator?
JE GETLEN
MOV DX,[DEFLEN] ; Default length
CALL HEXIN ; Second parameter present?
JC GETDEF ; If not, use default
MOV CX,4
CALL GETHEX ; Get ending address (same segment)
MOV CX,DX ; Low 16 bits of ending addr.
POP DX ; Low 16 bits of starting addr.
SUB CX,DX ; Compute range
JAE DSRNG2
DSRNG1:
JMP PERROR ; Negative range
DSRNG2:
INC CX ; Include last location
; JCXZ DSRNG1 ; Wrap around error
; Removing this instruction allows 0 FFFF to valid range
POP AX ; Restore segment
RET
GETDEF:
POP CX ; get original offset
PUSH CX ; save it
NEG CX ; rest of segment
JZ RNGRET ; use default
CMP CX,DX ; more room in segment?
JAE RNGRET ; yes, use default
JMP short RNGRET1 ; no, length is in CX
GETLEN:
INC SI ; Skip over "L" to length
MOV CX,4 ; Length may have 4 digits
CALL GETHEX ; Get the range
RNGRET:
MOV CX,DX ; Length
RNGRET1:
POP DX ; Offset
MOV AX,CX
ADD AX,DX
JNC OKRET
CMP AX,1
JAE DSRNG1 ; Look for wrap error
OKRET:
POP AX ; Segment
RET
DEFAULT:
; DI points to default address and CX has default length
CALL SCANP
JZ USEDEF ; Use default if no parameters
MOV [DEFLEN],CX
CALL RANGE
JMP GETEOL
USEDEF:
MOV SI,DI
LODSW ; Get default displacement
MOV DX,AX
LODSW ; Get default segment
RET
ifdef JAPAN
;
; Set Dump mode to Kanji or Ascii
;
dump_mode db 0
dbcs_flag db 0
dbcs_adj db 0
SETDUMPMODE:
call scanp ; get parameter
jz dm_err ; if none
lodsb
cmp al,'K' ; is it for Kanji mode
jnz @f ; no
call geteol
mov cs:dump_mode,1 ; set Kanji mode
jmp short dm_ret
@@:
cmp al,'A' ; is it for Ascii mode
jnz @f ; no
call geteol
mov cs:dump_mode,0 ; set Ascii mode
jmp short dm_ret
@@:
dm_err:
jmp PERR
dm_ret:
ret
endif
; Dump an area of memory in both hex and ASCII
DUMP:
ifdef JAPAN
mov cs:dbcs_flag,0
mov cs:dbcs_adj,0
endif
MOV BP,[DSSAVE]
MOV CX,DISPB
MOV DI,OFFSET DG:DEFDUMP
CALL DEFAULT ; Get range if specified
MOV DS,AX ; Set segment
ASSUME DS:NOTHING
MOV SI,DX ; SI has displacement in segment
PUSH SI ; save SI away
MOV AL,DSIZ
XOR AH,AH
XOR AX,-1
AND SI,AX ; convert to para number
MOV DI,OFFSET DG:ARG_BUF ; Build the output str in arg_buf
CALL OUTSI ; display location
POP SI ; get SI back
; Determine where the registers display should begin.
MOV AX,SI ; move offset
MOV AH,3 ; spaces per byte
AND AL,DSIZ ; convert to real offset
MUL AH ; 3 char positions per byte of output
OR AL,AL ; at beginning?
JZ INROW ; if so, then no movement.
PUSH CX
MOV CX,AX
CALL TAB
POP CX
INROW:
PUSH SI ; Save address for ASCII dump
BYTE0:
CALL BLANK ; Space between bytes
BYTE1:
LODSB ; Get byte to dump
CALL HEX ; and display it
POP DX ; DX has start addr. for ASCII dump
DEC CX ; Drop loop count
JZ ASCII ; If through do ASCII dump
MOV AX,SI
TEST AL,DSIZ ; On row boundary?
JZ ENDROW
PUSH DX ; Didn't need ASCII addr. yet
TEST AL,7 ; On 8-byte boundary?
JNZ BYTE0
MOV AL,CHAR_MINUS ; Mark every 8 bytes with "-"
STOSB
JMP SHORT BYTE1
ENDROW:
CALL ASCII ; Show it in ASCII
MOV DI,OFFSET DG:ARG_BUF ; Build the output str in arg_buf
CALL OUTSI ; Get the address at start of line
JMP INROW ; Loop until count is zero
; Produce a dump of the ascii text characters. We take the current SI which
; contains the byte after the last one dumped. From this we determine how
; many spaces we need to output to get to the ascii column. Then we look at
; the beginning address of the dump to tsee how many spaces we need to indent.
ASCII:
PUSH CX ; Save count of remaining bytes
; Determine how many spaces to go until the ASCII column.
MOV AX,SI ; get offset of next byte
DEC AL
AND AL,DSIZ
INC AL
; AX now has the number of bytes that we have displayed: 1 to Dsiz+1.
; Compute characters remaining to be displayed. We *always* put the ASCII
; dump in column 51 (or whereever)
SUB AL,10H ; get negative of number
DEC AL ;
NEG AL ; convert to positive
CBW ; convert to word
; 3 character positions for each byte displayed.
MOV CX,AX
SHL AX,1
ADD CX,AX
; Compute indent for ascii dump
MOV AX,DX
AND AL,DSIZ
XOR AH,AH
ADD CX,AX
; Tab over
CALL TAB
; Set up for true dump
MOV CX,SI
MOV SI,DX
SUB CX,SI
ASCDMP:
LODSB ; Get ASCII byte to dump
ifdef JAPAN
cmp cs:dbcs_flag,1
jz set_dbcs ; if it was lead byte
cmp cs:dbcs_flag,2
jnz @f ; if it was not tail byte
mov cs:dbcs_flag,0 ; reset
@@:
call test_lead
jnc @f ; if this is not lead byte
cmp byte ptr [si],CHAR_BLANK
jae set_dbcs ; if tail byte is not control corde
mov al,CHAR_PERIOD
jmp short @f
set_dbcs:
inc cs:dbcs_flag
@@:
cmp cs:dump_mode,1
jnz @f ; if not Kanji mode
cmp cs:dbcs_adj,1
jnz kanjiprt ; if no need to adjust
mov al,' ' ; tail byte is displayed already
mov cs:dbcs_adj,0
jmp short kanjiprt
@@:
endif
CMP AL,CHAR_RUBOUT
JAE NOPRT ; Don't print RUBOUT or above
ifdef JAPAN
kanjiprt:
endif
CMP AL,CHAR_BLANK
JAE PRIN ; print space through RUBOUT-1
NOPRT:
MOV AL,CHAR_PERIOD ; If unprintable character
PRIN:
STOSB
LOOP ASCDMP ; CX times
ifdef JAPAN
cmp cs:dump_mode,1
jnz @f ; if not Kanji mode
cmp cs:dbcs_flag,1
jnz @f ; if not ended with lead byte
mov al,[si] ; get tail byte
stosb
mov cs:dbcs_adj,1
@@:
endif
MOV AL,0
STOSB
PUSH DS
PUSH CS
POP DS
ASSUME DS:DG
CALL HEX_ADDRESS_STR
CALL CRLF
POP DS
ASSUME DS:NOTHING
POP CX ; Restore overall dump len
MOV WORD PTR [DEFDUMP],SI
MOV WORD PTR [DEFDUMP+WORD],DS ; Save last address as def
RET
ASSUME DS:DG
; Block move one area of memory to another Overlapping moves are performed
; correctly, i.e., so that a source byte is not overwritten until after it has
; been moved.
MOVE:
CALL DSRANGE ; Get range of source area
PUSH CX ; Save length
PUSH AX ; Save segment
PUSH DX ; Save source displacement
CALL ADDRESS ; Get destination address (sam
CALL GETEOL ; Check for errors
POP SI
MOV DI,DX ; Set dest. displacement
POP BX ; Source segment
MOV DS,BX
MOV ES,AX ; Destination segment
POP CX ; Length
CMP DI,SI ; Check direction of move
SBB AX,BX ; Extend the CMP to 32 bits
JB COPYLIST ; Move forward into lower mem.
; Otherwise, move backward. Figure end of source and destination
; areas and flip direction flag.
DEC CX
ADD SI,CX ; End of source area
ADD DI,CX ; End of destination area
STD ; Reverse direction
INC CX
COPYLIST:
MOVSB ; Do at least 1 - Range is 1-1
DEC CX
REP MOVSB ; Block move
RET1:
RET
; Fill an area of memory with a list values. If the list
; is bigger than the area, don't use the whole list. If the
; list is smaller, repeat it as many times as necessary.
FILL:
CALL DSRANGE ; Get range to fill
PUSH CX ; Save length
PUSH AX ; Save segment number
PUSH DX ; Save displacement
CALL LIST ; Get list of values to fill w
POP DI ; Displacement in segment
POP ES ; Segment
POP CX ; Length
CMP BX,CX ; BX is length of fill list
MOV SI,OFFSET DG:BYTEBUF ; List is in byte buffer
JCXZ BIGRNG
JAE COPYLIST ; If list is big, copy part of
BIGRNG:
SUB CX,BX ; How much bigger is area than
XCHG CX,BX ; CX=length of list
PUSH DI ; Save starting addr. of area
REP MOVSB ; Move list into area
POP SI
; The list has been copied into the beginning of the
; specified area of memory. SI is the first address
; of that area, DI is the end of the copy of the list
; plus one, which is where the list will begin to repeat.
; All we need to do now is copy [SI] to [DI] until the
; end of the memory area is reached. This will cause the
; list to repeat as many times as necessary.
MOV CX,BX ; Length of area minus list
PUSH ES ; Different index register
POP DS ; requires different segment r
JMP SHORT COPYLIST ; Do the block move
; Search a specified area of memory for given list of bytes.
; Print address of first byte of each match.
SEARCH:
CALL DSRANGE ; Get area to be searched
PUSH CX ; Save count
PUSH AX ; Save segment number
PUSH DX ; Save displacement
CALL LIST ; Get search list
DEC BX ; No. of bytes in list-1
POP DI ; Displacement within segment
POP ES ; Segment
POP CX ; Length to be searched
SUB CX,BX ; minus length of list
SCAN:
MOV SI,OFFSET DG:BYTEBUF ; List kept in byte buffer
LODSB ; Bring first byte into AL
DOSCAN:
SCASB ; Search for first byte
LOOPNE DOSCAN ; Do at least once by using LO
JNZ RET1 ; Exit if not found
PUSH BX ; Length of list minus 1
XCHG BX,CX
PUSH DI ; Will resume search here
REPE CMPSB ; Compare rest of string
MOV CX,BX ; Area length back in CX
POP DI ; Next search location
POP BX ; Restore list length
JNZ TTEST ; Continue search if no match
DEC DI ; Match address
CALL OUTDI ; Print it
INC DI ; Restore search address
CALL HEX_ADDRESS_ONLY ; Print the addresss
CALL CRLF
TTEST:
JCXZ RET1
JMP SHORT SCAN ; Look for next occurrence
; Get the next parameter, which must be a hex number.
; CX is maximum number of digits the number may have.
;=========================================================================
; GETHX: This routine calculates the binary representation of an address
; entered in ASCII by a user. GETHX has been modified to provide
; support for sector addresses > 32mb. To do this the bx register
; has been added to provide a 32 bit address. BX is the high word
; and DX is the low word. For routines that rely on DX for a 16
; bit address, the use of BX will have no effect.
;
; Date : 6/16/87
;=========================================================================
GETHX:
CALL SCANP
GETHX1:
XOR DX,DX ; Initialize the number
xor bx,bx ;an000;initialize high word for
; sector address
CALL HEXIN ; Get a hex digit
JC HXERR ; Must be one valid digit
MOV DL,AL ; First 4 bits in position
GETLP:
INC SI ; Next char in buffer
DEC CX ; Digit count
CALL HEXIN ; Get another hex digit?
JC RETHX ; All done if no more digits
STC
JCXZ HXERR ; Too many digits?
call ADDRESS_32_BIT ;an000;multiply by 32
JMP SHORT GETLP ; Get more digits
GETHEX:
CALL GETHX ; Scan to next parameter
JMP SHORT GETHX2
GETHEX1:
CALL GETHX1
GETHX2:
JC PERROR
RETHX:
CLC
HXERR:
RET
; Check if next character in the input buffer is a hex digit
; and convert it to binary if it is. Carry set if not.
HEXIN:
MOV AL,[SI]
; Check if AL is a hex digit and convert it to binary if it
; is. Carry set if not.
HEXCHK:
SUB AL,CHAR_ZERO ; Kill ASCII numeric bias
JC RET2
CMP AL,10
CMC
JNC RET2 ; OK if 0-9
AND AL,5FH
SUB AL,7 ; Kill A-F bias
CMP AL,10
JC RET2
CMP AL,16
CMC
RET2:
RET
; Process one parameter when a list of bytes is
; required. Carry set if parameter bad. Called by LIST.
LISTITEM:
CALL SCANP ; Scan to parameter
CALL HEXIN ; Is it in hex?
JC STRINGCHK ; If not, could be a string
MOV CX,2 ; Only 2 hex digits for bytes
push bx ;an000;save it - we stomp it
CALL GETHEX ; Get the byte value
pop bx ;an000;restore it
MOV [BX],DL ; Add to list
INC BX
GRET:
CLC ; Parameter was OK
RET
STRINGCHK:
MOV AL,[SI] ; Get first character of param
CMP AL,SINGLE_QUOTE ; String?
JZ STRING
CMP AL,DOUBLE_QUOTE ; Either quote is all right
JZ STRING
STC ; Not string, not hex - bad
RET
STRING:
MOV AH,AL ; Save for closing quote
INC SI
STRNGLP:
LODSB ; Next char of string
CMP AL,CR ; Check for end of line
JZ PERR ; Must find a close quote
CMP AL,AH ; Check for close quote
JNZ STOSTRG ; Add new character to list
CMP AH,[SI] ; Two quotes in a row?
JNZ GRET ; If not, we're done
INC SI ; Yes - skip second one
STOSTRG:
MOV [BX],AL ; Put new char in list
INC BX
JMP SHORT STRNGLP ; Get more characters
; Get a byte list for ENTER, FILL or SEARCH. Accepts any number
; of 2-digit hex values or character strings in either single
; (') or double (") quotes.
LIST:
MOV BX,OFFSET DG:BYTEBUF ; Put byte list in the byte buffer
LISTLP:
CALL LISTITEM ; Process a parameter
JNC LISTLP ; If OK, try for more
SUB BX,OFFSET DG:BYTEBUF ; BX now has no. of bytes in list
JZ PERROR ; List must not be empty
; Make sure there is nothing more on the line except for
; blanks and carriage return. If there is, it is an
; unrecognized parameter and an error.
GETEOL:
CALL SCANB ; Skip blanks
JNZ PERROR ; Better be a RETURN
RET3:
RET
; Command error. SI has been incremented beyond the command letter so it must
; decremented for the error pointer to work.
PERR:
DEC SI
; Syntax error. SI points to character in the input buffer which caused
; error. By subtracting from start of buffer, we will know how far to tab
; over to appear directly below it on the terminal. Then print "^ Error".
PERROR:
SUB SI,OFFSET DG:(BYTEBUF-1) ; How many char processed so far?
MOV CX,SI ; Parameter for TAB in CX
MOV DI,OFFSET DG:ARG_BUF ;
CALL TAB ; Directly below bad char
MOV BYTE PTR [DI],0 ; nul terminate the tab
MOV DX,OFFSET DG:SYNERR_PTR ; Error message
; Print error message and abort to command level
PRINT:
CALL PRINTF_CRLF
JMP COMMAND
; Gets an address in Segment:Displacement format. Segment may be omitted
; and a default (kept in BP) will be used, or it may be a segment
; register (DS, ES, SS, CS). Returns with segment in AX, OFFSET in DX.
ADDRESS:
CALL GET_ADDRESS
JC PERROR
ADRERR:
STC
RET
GET_ADDRESS:
CALL SCANP
MOV AL,[SI+1]
CMP AL,UPPER_S
JZ SEGREG
MOV CX,4
CALL GETHX
JC ADRERR
MOV AX,BP ; Get default segment
CMP BYTE PTR [SI],CHAR_COLON
JNZ GETRET
PUSH DX
GETDISP:
INC SI ; Skip over ":"
MOV CX,4
CALL GETHX
POP AX
JC ADRERR
GETRET:
CLC
RET
SEGREG:
MOV AL,[SI]
MOV DI,OFFSET DG:SEGLET ; SEGLET DB "CSED"
MOV CX,4
REPNE SCASB
JNZ ADRERR
INC SI
INC SI
SHL CX,1
MOV BX,CX
CMP BYTE PTR [SI],CHAR_COLON
JNZ ADRERR
PUSH [BX+DSSAVE]
JMP SHORT GETDISP
SEGLET DB "CSED" ; First letter of each of the segregs: CS,SS,ES,DS
; Short form of ENTER command. A list of values from the
; command line are put into memory without using normal
; ENTER mode.
GETLIST:
CALL LIST ; Get the bytes to enter
POP DI ; Displacement within segment
POP ES ; Segment to enter into
MOV SI,OFFSET DG:BYTEBUF ; List of bytes is in byte buffer
MOV CX,BX ; Count of bytes
REP MOVSB ; Enter that byte list
RET
; Enter values into memory at a specified address. If the line contains
; nothing but the address we go into "enter mode", where the address and its
; current value are printed and the user may change it if desired. To change,
; type in new value in hex. Backspace works to correct errors. If an illegal
; hex digit or too many digits are typed, the bell is sounded but it is
; otherwise ignored. To go to the next byte (with or without change), hit
; space bar. To back CLDto a previous address, type "-". On every 8-byte
; boundary a new line is started and the address is printed. To terminate
; command, type carriage return.
; Alternatively, the list of bytes to be entered may be included on the
; original command line immediately following the address. This is in regular
; LIST format so any number of hex values or strings in quotes may be entered.
ENTERDATA:
MOV BP,[DSSAVE] ; Set default segment to DS
CALL ADDRESS
PUSH AX ; Save for later
PUSH DX
CALL SCANB ; Any more parameters?
JNZ GETLIST ; If not end-of-line get list
POP DI ; Displacement of ENTER
POP ES ; Segment
GETROW:
CALL OUTDI ; Print address of entry
PUSH DI
PUSH ES
PUSH DS
POP ES
MOV DI,OFFSET DG:ARG_BUF
CALL BLANK
XOR AL,AL
STOSB
CALL HEX_ADDRESS_STR
POP ES
POP DI
GETBYTE:
MOV AL,ES:[DI] ; Get current value
PUSH DI
PUSH ES
PUSH DS
POP ES
MOV DI,OFFSET DG:ARG_BUF
CALL HEX ; And display it
MOV AL,CHAR_PERIOD
STOSB
XOR AL,AL
STOSB
MOV DX,OFFSET DG:ARG_BUF_PTR
CALL STD_PRINTF
POP ES
POP DI
LOOK_AGAIN:
MOV CX,2 ; Max of 2 digits in new value
MOV DX,0 ; Intial new value
GETDIG:
CALL INPT ; Get digit from user
MOV AH,AL ; Save
CALL HEXCHK ; Hex digit?
XCHG AH,AL ; Need original for echo
JC NOHEX ; If not, try special command
MOV DH,DL ; Rotate new value
MOV DL,AH ; And include new digit
LOOP GETDIG ; At most 2 digits
; We have two digits, so all we will accept now is a command.
DWAIT:
CALL INPT ; Get command character
NOHEX:
CMP AL,CHAR_BACKSPACE ; Backspace
JZ BS
CMP AL,CHAR_RUBOUT ; RUBOUT
JZ RUB
CMP AL,CHAR_MINUS ; Back up to previous address
JZ PREV
CMP AL,CR ; All done with command?
JZ EOL
CMP AL,CHAR_BLANK ; Go to next address
JZ NEXT
MOV AL,CHAR_BACKSPACE
CALL OUT_CHAR ; Back up over illegal character
CALL BACKUP
JCXZ DWAIT
JMP SHORT GETDIG
RUB:
MOV AL,CHAR_BACKSPACE
CALL OUT_char
BS:
CMP CL,2 ; CX=2 means nothing typed yet
JZ PUTDOT ; Put back the dot we backed up over
INC CL ; Accept one more character
MOV DL,DH ; Rotate out last digit
MOV DH,CH ; Zero this digit
CALL BACKUP ; Physical backspace
JMP SHORT GETDIG ; Get more digits
PUTDOT:
MOV AL,CHAR_PERIOD
CALL OUT_CHAR
JMP LOOK_AGAIN
; If new value has been entered, convert it to binary and
; put into memory. Always bump pointer to next location
STORE:
CMP CL,2 ; CX=2 means nothing typed yet
JZ NOSTO ; So no new value to store
; Rotate DH left 4 bits to combine with DL and make a byte value
PUSH CX
MOV CL,4
SHL DH,CL
POP CX
OR DL,DH ; Hex is now converted to binary
MOV ES:[DI],DL ; Store new value
NOSTO:
INC DI ; Prepare for next location
RET
NEXT:
CALL STORE ; Enter new value
INC CX ; Leave a space plus two for
INC CX ; each digit not entered
PUSH DI
MOV DI,OFFSET DG:ARG_BUF
PUSH ES
PUSH DS
POP ES
CALL TAB
XOR AL,AL
STOSB
MOV DX,OFFSET DG:ARG_BUF_PTR
CALL STD_PRINTF
POP ES
POP DI
MOV AX,DI ; Next memory address
AND AL,7 ; Check for 8-byte boundary
JZ NEWROW ; Take 8 per line
JMP GETBYTE
NEWROW:
CALL CRLF ; Terminate line
JMP GETROW ; Print address on new line
PREV:
CALL STORE ; Enter the new value
; DI has been bumped to next byte. Drop it 2 to go to previous addr
DEC DI
DEC DI
JMP SHORT NEWROW ; Terminate line after backing CLD
EOL:
CALL STORE ; Enter the new value
JMP CRLF ; CR/LF and terminate
; Console input of single character
IF SYSVER
INPT: ;*** change for build - label to inpt
PUSH DS
PUSH SI
LDS SI,CS:[CIN]
MOV AH,4
CALL DEVIOCALL
POP SI
POP DS
CMP AL,3
JNZ NOTCNTC
INT VEC_CTRL_BREAK ;23H
NOTCNTC:
CMP AL,UPPER_P - CHAR_AT_SIGN
JZ PRINTON
CMP AL,UPPER_N - CHAR_AT_SIGN
JZ PRINTOFF
CALL OUT_CHAR
RET
PRINTOFF:
PRINTON:
NOT [PFLAG]
JMP SHORT IN
ELSE
INPT: ; Change label for build
MOV AH,Std_Con_Input ;OPTION=1, STANDARD CONSOLE INPUT
INT 21H
RET
ENDIF
OUT_CHAR:
PUSH DI
PUSH DX
PUSH ES
PUSH DS
POP ES
MOV DI,OFFSET DG:ONE_CHAR_BUF
STOSB
MOV AL,0
STOSB
MOV DX,OFFSET DG:ONE_CHAR_BUF_PTR
CALL STD_PRINTF
POP ES
POP DX
POP DI
RET
;=========================================================================
; ADDRESS_32_BIT: This routine will build an address for 32bit sector
; addressibility. BX will be the high word, with DX being
; the low word.
;
; Inputs : DX/BX - registers to contain 32bit sector address
; DX & BX are both initialized to 0 on first call to routine.
;
; Outputs: DX/BX - registers to contain 32bit sector address
;
; Date : 6/16/87
;=========================================================================
ADDRESS_32_BIT proc near ;an000;perform 32 bit address
; creation
push cx ;an000;save affected regs.
mov cx,04h ;an000;initialize to
; nibble shift
; $do ;an000;while cx not= 0
$$DO1:
cmp cx,00h ;an000;are we done?
; $leave e ;an000;yes, quit loop
JE $$EN1
shl bx,1 ;an000;shift bx 1 bit
shl dx,1 ;an000;shift dx 1 bit
; $if c ;an000;did low word carry
JNC $$IF3
or bx,01h ;an000;set bit 0 of high word
; $endif ;an000;
$$IF3:
dec cx ;an000;decrease counter
; $enddo ;an000;end while loop
JMP SHORT $$DO1
$$EN1:
or dl, al ;an000;overlay low word
; bits 0-3 with next
; portion of the address
pop cx ;an000;restore affected regs.
ret ;an000;return to caller
ADDRESS_32_BIT endp ;an000;end proc
CODE ENDS
END DEBCOM1