|
|
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
|