home *** CD-ROM | disk | FTP | other *** search
- PAGE ,132
- TITLE LOOKMEM - LOOK AT MEMORY
- SUBTTL LOOK AT MEMORY IN ANY SEGMENT
-
- ; SET TABS TO 8
- ; ;
- ;***************************************************************************;
- ; ;
- ; LOOKMEM Version 8/29/88 ;
- ; ;
- ; Copyright (C) John Pulliam 1988 ;
- ; ;
- ; For Columbia Data Product Computers and Compatibles ;
- ; Released to Public Domain ;
- ; ;
- ;***************************************************************************;
- ; ;
- ; LOOKMEM is a program that lets you take a peek at the contents of the ;
- ; RAM or ROM memory in your IBM compatible computer. Only the first 1 Meg ;
- ; of memory may be viewed this way. ;
- ; ;
- ; Usage of this program is to just enter the name, "LOOKMEM" and follow ;
- ; the prompts on the screen. ;
- ; ;
- ; This is a new version of LOOKMEM, which was originally released in 1984. ;
- ; The primary change is in the method of writing to the display. The old ;
- ; version used the DOS functions and was therefore quite slow. This new ;
- ; version uses direct screen writes, taking care not to cause any of the ;
- ; snow on the screen as is common with many machines. As a result of the ;
- ; different method of writing to the display, computer systems that are ;
- ; not very compatible will likely not run this program properly. ;
- ; ;
- ; An addition is the Find Function for searching memory for a sequence or ;
- ; string of hex bytes and the Repeat Find fun to find the next occurrence ;
- ; of the same string. ;
- ; ;
- ; Another small change is that the right and left arrow keys now increment ;
- ; the segment by 10 hex instead of by one as before. ;
- ; ;
- ; The author of this program takes no responsibility for any damages ;
- ; allegedly caused by the use or operation of this program, whether it be ;
- ; to software, hardware, furniture, household appliances, pets or personal ;
- ; belongings. ;
- ; ;
- ; MS-DOS, PC-DOS, IBM, etc. are copyrighted. ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- CSEG SEGMENT PARA PUBLIC
- ASSUME CS:CSEG,DS:CSEG,ES:CSEG
-
- ORG 100H
-
- ; Define the constants
-
- CR EQU 13 ; Carriage return code
- LF EQU 10 ; Line feed code
- BS EQU 08 ; Backspace code
- QT EQU 34 ; Quote symbol
- BYT EQU 16 ; Number of bytes per line
- LINES EQU 8 ; Number of lines to display
-
- ; Set up the segment registers
-
- LOOKMEM:MOV AX,CS ; Get current segment
- MOV DS,AX ; Set DS to this seg
- MOV ES,AX ; Set ES to this seg
- MOV SEGADD,AX ; Initialize display segment
- CALL INIT ; Get screen & cursor parameters
-
- SIGNON: MOV AH,6 ; Line number
- MOV AL,1 ; Column number
- MOV SI,OFFSET HELLO ; Text
- CALL WRITE ; Display text on screen
-
- ; Ask for the segment to display memory from
-
- GETSEG: MOV SI,OFFSET SEGMSG ; Address of message
- MOV AX,0801H ; Line 8 / column 1
- PUSH AX
- CALL WRITE ; Display string function
- POP DX
- ADD DL,LEN_SEGMSG
- DEC DH
- CALL CURSE ; Position the cursor at right end of prompt
-
- ; Read desired segment
- ; Keep the same segment if user just presses return
-
- MOV BX,OFFSET SEGADD; Where to store hex input
- CALL GETCHARS ; Get input from keyboard
- JC GETSEG ; Repeat query if illegal input
-
- ; Ask for the starting offset to display memory from
-
- GETOFF: MOV SI,OFFSET STMSG ; Address of message
- MOV AX,0901H ; Line & column
- PUSH AX
- CALL WRITE
- POP DX
- ADD DL,LEN_STMSG
- DEC DH
- CALL CURSE ; Position the cursor
-
- ; Read desired offset
- ; Keep the same offset if user just presses return
-
- MOV BX,OFFSET OFFADD; Where to store hex input
- CALL GETCHARS ; Get input from keyboard
- JC GETOFF ; Repeat query if illegal input
- CALL HIDECUR ; Move cursor off the screen to hide it
-
- ; Display the segment, offset & data
-
- DISLOOP:CALL DSEGOFF ; Show user segment and offset he chose
- CALL DISPLA ; Display memory (at last)
-
- ; Display the user prompt on the bottom of the screen
-
- PRTPROM:MOV SI,OFFSET USRPROM ; Point to prompt
- MOV AX,24*256+1 ; Row & column
- PUSH AX
- CALL WRITE
- POP DX
- ADD DL,LEN_PROM
- DEC DH
- CALL CURSE ; Position the cursor
-
- ; Check for any key inputs
-
- GETINP: MOV AH,8 ; Console input: no echo
- INT 21H ; Read
- OR AL,AL ; Extended code ?
- JZ GETINP_10 ; Go handle cursor controls
- CMP AL,01BH ; Escape ?
- JNE GETINP_0 ; No, try for others
- JMP EXIT ; Yes, leave
-
- GETINP_0:
- CMP AL,CR ; Return or enter ?
- JNE GETINP_1 ; No, check others
- MOV AX,24*256+1 ; Row / column
- MOV SI,OFFSET BLANKS
- CALL WRITE ; Clear user prompt
- MOV AX,900H + LEN_STMSG+2 ; Line & column
- MOV SI,OFFSET SPACES4
- CALL WRITE ; Clear previous selected offset
- JMP GETSEG ; Yes, go get new values for seg/off
- GETINP_1:
- CMP AL,'8' ; Is it unshifted up arrow or '8' key ?
- JE GETINP_10A ; Handle as up arrow
- GETINP_2:
- CMP AL,'2' ; Is it unshifted down arrow or '2' key ?
- JE GETINP_11A ; Yes, handle as down arrow
- GETINP_3:
- CMP AL,'4' ; Unshifted left arrow or '4' key ?
- JNE GETINP_4
- JMP GETINP_13A ; Map to shift left
- GETINP_4:
- CMP AL,'6' ; Unshifted right arrow or '6' key ?
- JNE GETINP_9
- JMP GETINP_14A
- GETINP_9:
- MOV DL,7 ; Beep. we don't understand
- MOV AH,2
- INT 21H
- JMP GETINP ; Loop for more input
-
- ; Process extended key scan codes
-
- GETINP_10:
- INT 21H ; Get second scan code
- CMP AL,72 ; Cursor up ?
- JNE GETINP_11 ; No
- GETINP_10A:
- MOV AX,OFFADD
- ADD AX,80H ; Increment starting offset (wraps at top)
- MOV OFFADD,AX ; Put it back
- JMP DISLOOP ; Print seg/off and bytes
- GETINP_11:
- CMP AL,80 ; Down arrow
- JNE GETINP_12 ; Nope
- GETINP_11A:
- MOV AX,OFFADD
- SUB AX,80H ; Decrement (will wrap if bottom)
- MOV OFFADD,AX ; Put it back
- JMP DISLOOP ; Display new offset and bytes
- GETINP_12:
- CMP AL,59 ; Help ?
- JNE GETINP_12A ; No
-
- CALL CLRSCRN ; Clear bottom of the screen
- MOV SI,OFFSET HELPMSG; Point to help
- MOV AX,0E01H ; Line 14 & column 1
- CALL WRITE
- CALL HIDECUR ; Move cursor off the screen to hide it
-
- MOV AH,8 ; Wait for any key to be pressed
- INT 21H
- OR AL,AL
- JNZ DL1 ; Skip if not extended key input
-
- MOV AH,6 ; Get second code of extended pair
- MOV DL,0FFH
- INT 21H
-
- DL1: CALL CLRSCRN ; Clear bottom of the screen
- JMP DISLOOP ; Get from keyboard
-
- GETINP_12A:
- CMP AL,60 ; Find ?
- JNE GETINP_12B ; Nope
- CALL CLRSCRN ; Clear bottom of the screen
- CALL FINDIT ; Go "find" a string
- JMP DISLOOP
-
- GETINP_12B:
- CMP AL,61 ; Repeat Find ?
- JNE GETINP_13 ; Nope
- CALL CLRSCRN ; Clear bottom of the screen
- MOV DI,OFFADD ; Current offset
- INC DI ; Start at the NEXT location
- MOV AX,SEGADD ; Get starting segment to search from
- CALL REP_FIND ; Go "find" the same string
- JMP DISLOOP
-
- GETINP_13:
- CMP AL,75 ; Left arrow ?
- JNE GETINP_14 ; No
- GETINP_13A:
- SUB SEGADD,10H ; Decrement seg by 10 hex (wrap at bottom)
- JMP DISLOOP
- GETINP_14:
- CMP AL,77 ; Right arrow ?
- JNE GETINP_20 ; No
- GETINP_14A:
- ADD SEGADD,10H ; Increment seg by 10 hex (wrap at top)
- JMP DISLOOP
- GETINP_20:
- JMP GETINP_9
-
- EXIT: CALL RESET ; Reset Video Mode and Active Page
- INT 20H ; Return to DOS
-
- .XLIST
- SUBTTL MISCELLANEOUS CALLABLE ROUTINES
- PAGE +
- .LIST
- ; ;
- ;***************************************************************************;
- ; ;
- ; Number Input Subroutine ;
- ; ;
- ; Get four digit number from keyboard, convert to hex and store it ;
- ; in [BX] ;
- ; ;
- ; Backspace and carriage return codes are processed by DOS ;
- ; ;
- ; Alters: All registers are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- GETCHARS:
- MOV AH,4 ; Max number of characters wanted
- MOV DI,OFFSET KBUFSZ ; Keyboard buffer
- CALL KYBD ; Input reply
-
- CMP AH,4 ; Want 4 chars excluding the CR
- JE GC1 ; Skip if no leading zeros
-
- ; Skip to return if user just presses return
-
- OR AH,AH ; Just return pressed ?
- JZ GC2
- CALL INSERT ; Insert leading zeros
-
- ; Convert four ASCII codes into two hex bytes (four hex digits)
-
- GC1: MOV AX,WORD PTR KBUF ; First two ASCII codes
- CALL ASC_HEX ; Returns one hex byte
- JC GC2 ; Repeat query if illegal input
- MOV CS:[BX+1],AL ; Store high segment byte
- MOV AX,WORD PTR KBUF+2 ; Third and fourth ASCII codes
- CALL ASC_HEX ; Returns one hex byte
- JC GC2 ; Repeat query if illegal input
- MOV CS:[BX],AL ; Store low segment byte
-
- GC2: JNC GC4
- MOV DL,7 ; Beep. we don't understand
- MOV AH,2
- INT 21H
- STC
- GC4: RET
-
- ; ;
- ;***************************************************************************;
- ; ;
- ; Insert Leading Zeros Subroutine ;
- ; ;
- ; Insert leading zeros into keyboard input buffer, KBUF ;
- ; ;
- ; Alters: All registers are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- INSERT: STD ; Reverse
- MOV AL,4 ; Number of digits in the number
- SUB AL,AH ; Number of leading zeros to insert
- INS1: MOV DI,OFFSET KBUF+3 ; Destination address
- MOV SI,OFFSET KBUF+2 ; Source address
- MOV CX,3 ; Loop count
- INS2: REP MOVSB ; Move three characters right one place
- MOV BYTE PTR [DI],'0'; Insert ASCII zero into left place
- DEC AL
- JNZ INS1 ; Loop for each zero to add
- CLD ; Forward
- RET ; Return to caller
-
- PAGE
- ; ;
- ;***************************************************************************;
- ; ;
- ; Write CR LF To CRT ;
- ; ;
- ; Alters: All registers are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- CRLF: MOV SI,OFFSET CRLFM ; Address of 'CR,LF'
- XOR AX,AX ; Same row & column
- CALL WRITE ; Write CR, LF
- RET ; Return to continue
- CRLFM DB CR,LF,'$'
-
-
- ; ;
- ;***************************************************************************;
- ; ;
- ; HIDECUR - Hide The Cursor Off-Screen ;
- ; ;
- ; Alters: All registers except DI, SI & ES are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- HIDECUR:
- PUSH DI ; Save registers
- PUSH SI
- PUSH ES
- MOV DL,79
- MOV DH,26 ; Move cursor off the screen to hide it
- CALL CURSE
- POP ES
- POP SI
- POP DI
- RET
-
- PAGE
- ; ;
- ;***************************************************************************;
- ; ;
- ; Display The Selected Memory ;
- ; ;
- ; Entry: Segadd = Segment to display from ;
- ; Stadd = Offset to display from ;
- ; Ascseg = ASCII code of segment ;
- ; Ascadd = ASCII code of offset ;
- ; ;
- ; Alters: All registers are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- DISPLA: PUSH OFFADD ; Save starting offset
- PUSH ES ; Save ES register
- MOV SI,OFFSET SEGO ; "Seg Off" string
- MOV AX,1 ; Left end of same line
- CALL WRITE ; Output text
-
- ; Output the top line - hex display on left of screen
-
- MOV CX,BYT ; Number of bytes per line
- MOV AL,BYTE PTR OFFADD ; Get the low address byte
- LUP1: PUSH AX ; Save for next output
- CALL HEX_ASC ; Convert to ASCII
- MOV SI,OFFSET ASCTOP
- MOV BYTE PTR [SI],AH; Save low digit for output
- XOR AX,AX ; Keep same line & column
- CALL WRITE ; Write it to the display
- POP AX ; Get previous digit
- INC AL ; Increment for next digit
- LOOP LUP1 ; Repeat for the rest of the line
- XOR AX,AX ; Same line & column
- MOV SI,OFFSET SPACE ; Follow with a blank
- CALL WRITE
-
- ; Output top line - ASCII display on right of screen
-
- MOV CX,BYT ; Number of bytes per line
- MOV AL,BYTE PTR OFFADD ; Get the low address byte
- LUP2: PUSH AX ; Save for next output
- CALL HEX_ASC ; Convert to ASCII
- MOV SI,OFFSET ASCTOP2
- MOV BYTE PTR [SI],AH; Store low digit for display later
- XOR AX,AX ; Same row & column
- CALL WRITE ; Write it on the display
- POP AX ; Get previous digit
- INC AL ; Increment for next digit
- LOOP LUP2 ; Repeat for the rest
- CALL CRLF ; CR and LF
-
- MOV BX,LINES ; Number of lines to display
- MOV ES,SEGADD ; Fetch segment to display
-
- ; Loop here for each line to display
-
- LUP3: PUSH BX ; Save line counter
-
- ; Output address at start of line
-
- ; Print the segment address on the left margin along with the offset
-
- MOV SI,OFFSET SSTO ; Point to the ASCII segment
- MOV AX,1 ; Left end of same line
- CALL WRITE ; Display the segment
- XOR AX,AX ; Print a colon between segment & offset
- MOV SI,OFFSET COLON
- CALL WRITE ; Colon
- MOV AL,BYTE PTR OFFADD+1 ; Get the first address byte
- CALL HEX_ASC ; Convert to ASCII
- MOV ASCADD,AX ; Save for output to crt
- MOV AL,BYTE PTR OFFADD ; Get the second address byte
- CALL HEX_ASC ; Convert it to ASCII too
- MOV ASCADD+2,AX ; And save it also
-
- XOR AX,AX
- MOV SI,OFFSET ASCADD; Display the offset
- CALL WRITE
- MOV SI,OFFADD ; Get starting offset
- ADD OFFADD,BYT ; Inc address by number of bytes in a line
- ; for the offset on the next line
-
- ; Output one line of data (hex display on left and ASCII display on right)
-
- MOV CX,BYT ; Number of bytes to display in a line
- MOV DI,OFFSET ASCCHAR ; Address of ASCII buffer (right end of crt)
-
- LUP4: MOV AL,ES:[SI] ; Pick up next memory byte to display
- PUSH SI ; Save this memory pointer
- PUSH AX ; Save memory byte
- CMP AL,7FH ; See if it can be displayed on crt
- JGE DASC1 ; Branch if not
- CMP AL,20H
- JGE DASC2 ; Branch if yes
- DASC1: MOV AL,'.' ; Substitute period
- DASC2: MOV [DI],AL ; Store for later display
- POP AX ; Retrieve memory byte
- CALL HEX_ASC ; Convert it to two ASCII codes
- MOV CHARS,AX ; Store them for the hex display
- XOR AX,AX
- MOV SI,OFFSET CHARS ; We stored the data here
- CALL WRITE ; Display the hex data
- POP SI ; Get last memory pointer
- INC SI ; Increment for next memory pointer
- INC DI ; Increment ASCII buffer pointer
- LOOP LUP4 ; Repeat until done with this line
-
- XOR AX,AX ; Spaces between hex display & ASCII display
- MOV SI,OFFSET SPACES
- CALL WRITE
-
- ; Output ASCII display on right of crt
-
- ; Can't write this as a string because there might be a '$' symbol in it
-
- MOV DI,NXT_POS ; Next position on display screen
- MOV SI,OFFSET ASCCHAR ; Point to the symbol to display
- MOV ES,SEGADD
- MOV CX,BYT ; Number of symbols to display
- LUP5: PUSH ES ; Save our memory segment to display from
- LODSB ; Next symbol to display
- MOV ES,SCREEN ; Fetch display segment
- CALL WRITE_ONE ; Display the symbol
- INC DI ; Skip past the attribute byte
- POP ES ; Get the segment to get data from
- LOOP LUP5 ; Repeat for all symbols
-
- CALL CRLF ; Output CR and LF
- POP BX ; Restore line counter
- DEC BX ; Decrement line counter
- JZ DISEND
- JMP LUP3 ; Repeat for all lines
-
- DISEND: POP ES ; Restore ES register
- POP OFFADD ; Restore starting offset
- RET ; Return to calling routine
-
- PAGE
- ; ;
- ;***************************************************************************;
- ; ;
- ; Keyboard Input Subroutine Version 2/19/84 ;
- ; ;
- ; This routine reads ASCII codes from the keyboard into a buffer ;
- ; ;
- ; Entry: AH = Max number of characters to read excluding any CR code ;
- ; DI = FWA of the buffer in which to store the characters ;
- ; ;
- ; Exit: AL = The last character read excluding any cr code ;
- ; AH = The number of characters read excluding BS or CR codes ;
- ; DI = address of the last character read ;
- ; One less than buffer FWA if only CR is received ;
- ; ;
- ; Backspace and carriage return codes are processed by DOS ;
- ; ;
- ; The buffer must have the first two bytes available for storage of ;
- ; the max number of characters to read and number of characters read ;
- ; including the carriage return code ;
- ; ;
- ; Alters: All registers except BX are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- KYBD: PUSH BX ; Save register
- PUSH DI ; Save buffer address
- INC AH ; Allow for the CR code
- MOV [DI],AH ; Store max number of words to read
- MOV AX,0C0AH ; Clear and read keyboard buffer
- MOV DX,DI ; Buffer address in DX
- INT 21H ; Call DOS
- POP DI ; Get buffer address
- INC DI
- MOV AH,[DI] ; Get number of characters read
- MOV BL,AH ; Put in base register
- XOR BH,BH
- ADD DI,BX ; Set DI to last character position
- MOV AL,[DI] ; Get last character read
- POP BX ; Restore register
- RET ; Return to calling routine
-
- PAGE
- ; ;
- ;***************************************************************************;
- ; ;
- ; Convert ASCII To Hex Version 3/24/84 ;
- ; ;
- ; Modified to allow lower case 'a' thru 'f' ;
- ; ;
- ; Convert two ASCII codes in AX to one hex number in AL ;
- ; ;
- ; Entry: AL = upper ASCII code ;
- ; AH = lower ASCII code ;
- ; Inputs must be '0' - '9', 'A' - 'F' or 'a' - 'f' ;
- ; ;
- ; Exit: AL = one hex number (two hex digits, 0 - 9, A - F) ;
- ; Carry flag is set if an illegal hex digit is in the input ;
- ; ;
- ; Alters: Registers AL and AH are altered ;
- ; ;
- ; Note: Valid for all hex numbers 00 to FF ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- ASC_HEX:PUSH BX ; Save registers
- MOV BX,AX ; Save the ASCII codes
- CALL CNVRT1 ; Returns upper digit in lower AL
- SHL AL,1 ; Put it in upper AL
- SHL AL,1
- SHL AL,1
- SHL AL,1
- XCHG AL,BH ; Save in BH & get lower digit
- CALL CNVRT1 ; Returns lower digit in lower AL
- OR AL,BH ; Combine both hex digits into AL
- POP BX ; Restore registers
- CLC ; Clear carry/error flag
- RET ; Return to calling routine
-
- CNVRT1: SUB AL,30H ; Partial conversion
- JL CERR ; Al < 0 => illegal hex code
-
- ; Allow lower case alpha input if legal hex
-
- CMP AL,9 ; Check for 0 - 9
- JLE CEND ; Al <= 9 => 0 - 9
- AND AL,0DFH ; Force capital letters of A thru F
- CMP AL,11H ; Check for A - F
- JL CERR ; Al < 11h => Illegal (between '9' and 'A')
- SUB AL,7 ; Convert A - F
- CMP AL,0FH ; Al > 0fh => Illegal
- JG CERR ; Error exit
- CEND: RET ; Return to continue
-
- CERR: POP AX ; Erase first return address
- SUB AX,AX ; Set result to zero
- POP BX ; Adjust stack
- STC ; Set carry/error flag
- RET ; Return to calling routine
-
- PAGE
- ; ;
- ;****************************************************************************;
- ; ;
- ; Convert Hex To ASCII Version 8/07/84 ;
- ; ;
- ; Convert from two hex digits in AL to two ASCII codes in AX ;
- ; ;
- ; Entry: AL = Hex number 00H to FFH ;
- ; ;
- ; Exit: AL = Upper ASCII code ;
- ; AH = Lower ASCII code ;
- ; ;
- ; Alters: registers AL and AH are altered ;
- ; ;
- ; Note: This conversion is valid for all hex codes ;
- ; ;
- ;****************************************************************************;
- ; ;
-
- HEX_ASC:
- MOV AH,AL ; Save upper hex digit
- CALL CVRT2 ; Convert hex lower digit
- XCHG AH,AL ; Save it in AH / get upper digit to convert
- SHR AL,1 ; Shift into low nibble
- SHR AL,1
- SHR AL,1
- SHR AL,1 ; Convert upper hex digit
-
- ; Convert one hex digit in lower nibble of AL into one ASCII code in AL
-
- CVRT2: AND AL,0FH ; Separate out one hex digit
- ADD AL,90H ; And convert
- DAA ; To one
- ADC AL,40H ; ASCII code
- DAA ; In AL
- CVRT4: RET ; Return to calling routine
-
- PAGE
- ; ;
- ;***************************************************************************;
- ; ;
- ; Display Current Segment And Offset ;
- ; ;
- ; Entry: None ;
- ; ;
- ; Exit: None ;
- ; ;
- ; Alters: registers AX, DX and SI are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- DSEGOFF:
- MOV AL,BYTE PTR SEGADD+1 ; Get the first segment byte
- CALL HEX_ASC ; Convert to ASCII
- MOV SSTO,AX ; Save for output to crt
- MOV AL,BYTE PTR SEGADD ; Get the second segment byte
- CALL HEX_ASC ; Convert it to ASCII too
- MOV SSTO[2],AX ; And save it also
-
- MOV AL,BYTE PTR OFFADD+1 ; Get the first offset byte
- CALL HEX_ASC ; Convert to ASCII
- MOV OFFSTO,AX ; Save for output to crt
- MOV AL,BYTE PTR OFFADD ; Get the second segment byte
- CALL HEX_ASC ; Convert it to ASCII too
- MOV OFFSTO[2],AX ; And save it also
-
- MOV SI,OFFSET CURSEG; Display segment
- MOV AH,11 ; Line no.
- MOV AL,1 ; Left end of line
- CALL WRITE
- MOV SI,OFFSET CUROFF; Display offset
- XOR AX,AX ; Keep current line and column
- CALL WRITE
- CALL DISPLIN
- RET
-
- ; ;
- ;***************************************************************************;
- ; ;
- ; Display A Line Of Underscores ;
- ; ;
- ; Entry: None ;
- ; ;
- ; Exit: None ;
- ; ;
- ; Alters: None ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- UL DB CR,LF,79 DUP('_'),'$'
-
- DISPLIN:
- PUSH CX ; Save registers
- PUSH BX
- PUSH AX
- MOV AX,1 ; Left end of current row
- MOV SI,OFFSET UL
- CALL WRITE
- POP AX ; Restore registers
- POP BX
- POP CX
- RET
-
- PAGE
- ; ;
- ;****************************************************************************;
- ; ;
- ; FIND a HEX string in memory ;
- ; ;
- ; FIND a string in memory starting from the current segment & offset+1 ;
- ; ;
- ; Entry: SEGADD = Starting segment where search starts ;
- ; OFFADD = Starting offset - 1 where search starts ;
- ; ;
- ; Exit: SEGADD = Segment where the string was found ;
- ; OFFADD = Starting offset of the string if found ;
- ; ;
- ; Alters: All registers are altered ;
- ; SEGADD & OFFADD are altered if the string is found ;
- ; The hex and ASCII displays will be shown on the CRT if found ;
- ; ;
- ;****************************************************************************;
- ; ;
-
- FINDIT: MOV AH,15 ; Line number
- MOV AL,1 ; Column number
- MOV SI,OFFSET FINDMSG
- CALL WRITE ; Display the prompt
- MOV DH,17 ; Position cursor in the prompt
- MOV DL,23
- MOV DI,OFFSET KBUF ; Where to store the ASCII bytes
- MOV WORD PTR SRCHCNT,0 ; Clear the count of symbols entered
-
- ; Loop here for each byte
-
- FIN2: PUSH DX ; Save cursor position
- CALL CURSE ; Position the cursor at right end of prompt
-
- ; Loop here for each symbol or digit
-
- MOV BL,0 ; Start with toggle = 0
-
- FIN4: MOV AX,0C01H ; Wait for any key to be pressed
- INT 21H ; Read the ASCII code
-
- ; Check for valid input
-
- CMP AL,CR ; Go do the search if CR key
- JE FIN5
-
- CMP AL,BS ; Check for backspace
- JE FIN8
- CMP AL,0
- JNZ FIN6 ; Quit if extended code
- FIN5: JMP FIN15
-
- FIN6: CMP AL,'0' ; Verify legal hex digit
- JL FIN7
- CMP AL,'9'
- JLE FIN13
- AND AL,0DFH ; Force capital letters
- CMP AL,'F'
- JG FIN7
- CMP AL,'A'
- JGE FIN13 ; Skip if valid hex digit
-
- ; Illegal symbol input
-
- FIN7: MOV DL,7 ; Beep, illegal input
- MOV AH,2
- INT 21H
- POP DX ; Cursor position
- PUSH DX
- CALL CURSE ; Move cursor back to where it was
-
- MOV DL,'_' ; Redisplay underline
- MOV AH,2
- INT 21H
- JMP SHORT FIN10 ; Skip to continue
-
- ; Backspace
-
- FIN8: DEC DI ; Decrement buffer location after backspace
- CMP DI,OFFSET KBUF
- JGE FIN11 ; Branch if not left end of buffer
- MOV DI,OFFSET KBUF
- MOV DL,7 ; Beep, illegal input at left end of buffer
- MOV AH,2
- INT 21H
- DEC WORD PTR SRCHCNT
-
- ; Backspace or Illegal symbol
-
- FIN10: POP DX ; Get cursor position
- PUSH DX
- CALL CURSE ; Restore cursor
- JMP FIN4 ; Loop for next input
-
- ; Backspace and not at left end of buffer
-
- FIN11: CMP BL,0 ; Check whether first or second digit of byte
- JNZ FIN12 ; Skip if toggle is not 0
- POP DX ; Cursor position
- DEC DL ; Dec cursor position
- PUSH DX ; Save position
- DEC DL ; Dec cursor position
- CALL CURSE ; Move cursor left one
-
- FIN12: MOV DL,'_' ; Redisplay underline
- MOV AH,2
- INT 21H
- POP DX
- DEC DL ; Dec cursor position
- PUSH DX
- CALL CURSE ; Move cursor left one
- XOR BL,1 ; Change toggle after backing up
- JMP FIN4 ; Loop for next input
-
- FIN13: XOR BL,1 ; Change toggle after symbol input
- STOSB ; Store the ASCII code in the keyboard buffer
- INC WORD PTR SRCHCNT
- POP DX ; Cursor position
- INC DL ; Bump cursor position
- PUSH DX ; Save new position
- CMP BL,0
- JZ FIN14
- JMP FIN4 ; Repeat for second digit
-
- FIN14: POP DX ; Get cursor position
- INC DL ; Move cursor position to next byte
-
- CMP DI,OFFSET KBUF+8
- JGE FIN16 ; Branch to do the search
- JMP FIN2 ; Loop for another symbol
-
- FIN15: POP DX ; Adjust stack
- CMP AL,0
- JNE FIN16
- JMP FIN30 ; Quit if extended code
-
- ; Convert the inputs to hex for the search
-
- FIN16: CALL CLRSCRN ; Clear bottom of the screen
- CALL HIDECUR ; Hide the cursor
-
- MOV CX,SRCHCNT ; Number of digits or symbols entered
- SHR CX,1 ; Number of hex bytes
- JCXZ FIN30 ; Quit if invalid - only 1 digit
- MOV SI,OFFSET KBUF ; Point to the ASCII string of bytes
- MOV DI,OFFSET SRCHCHR ; Destination
- FIN17: LODSW
- CALL ASC_HEX ; Convert to one hex byte
- STOSB
- LOOP FIN17 ; Loop for all bytes
-
- ; Now search from current SEG:OFF for the string of bytes just entered
-
- FIN18: PUSH ES ; Save ES segment
- MOV DI,OFFADD ; Current offset
- INC DI ; Start at the NEXT location
- MOV AX,SEGADD ; Get starting segment to search
- DEC AX
- MOV ES,AX ; Put first seg - 1 in ES
- CMP AX,0FFFFH
- JNE FIN20 ; Skip if not starting with segment zero
- INC AX
- JMP SHORT FIN22 ; Skip check for zero if starting at zero
-
- ; Start searching a new segment for the string. Quit after Segment FFFFH
-
- FIN20: MOV AX,ES ; Get the previous segment
- INC AX ; Step to next segment to scan
- OR AX,AX
- JNZ FIN22 ; Skip over "Not Found message
-
- MOV AH,18 ; Line number
- MOV AL,36 ; Column number
- MOV SI,OFFSET NOTFND
- CALL WRITE ; Display the prompt
- MOV DL,7 ; Beep
- MOV AH,2
- INT 21H
-
- MOV AL,12 ; Delay so message can be seen
- XOR CX,CX
- LOOP $
- DEC AL
- JNZ $-4
- JMP SHORT FIN29 ; Quit at end of memory
-
- ; Repeat Find Entry Point
-
- REP_FIND:
- PUSH ES
- CALL HIDECUR ; Hide the cursor
-
- FIN22: MOV ES,AX ; Put the segment in ES
-
- ; Search for the first character in the string for a starting point
-
- MOV CX,16
- MOV AL,SRCHCHR ; First hex byte in the string
- REPNE SCASB
- JE FIN24 ; Found the first symbol so go check for more
- SUB DI,DI ; Offset is 0 for the rest of the segments
- JMP SHORT FIN20 ; Loop to get the next segment
-
- ; Search for the string
-
- FIN24: DEC DI ; Point to the first symbol we just found
- MOV SI,OFFSET SRCHCHR ; Point to first symbol of string to find
- MOV CX,SRCHCNT ; Length of string to find
- SHR CX,1
- REPE CMPSB ;
- JE FIN28 ; Found it so skip to display it
- SUB DI,DI ; Offset is 0 for the rest of the segments
- JMP SHORT FIN20 ; Loop to get the next segment
-
- FIN28: MOV AX,SRCHCNT
- SHR AX,1
- SUB DI,AX ; Point to the start of the string we found
- MOV SEGADD,ES ; Save the segment where it was found
- MOV OFFADD,DI
-
- FIN29: POP ES ; Restore ES segment
- FIN30: RET ; Return to calling routine
-
- .XLIST
- SUBTTL Video & Display Subroutines
- .LIST
-
- CGA EQU 0B800H ; Screen segment - color/graphics
- MONO EQU 0B000H ; Screen segment - b & w adapter
-
- CGAFLG DB 0 ; 1 = CGA, 0 = MONO (default)
- SCREEN DW 0 ; Base segment of display screen
- RET_ADD DW 0 ; Address of Horizontal Retrace Status Register
-
- VMODE DB 0 ; Original video mode
- VCOL DB 0 ; Original number of video columns
- VPAGE DB 0 ; Original active video page
- CURSIZE DW 0 ; Original cursor size or lines
-
-
- ; ;
- ;***************************************************************************;
- ; ;
- ; Init - Initialize Screen Routines ;
- ; ;
- ; Entry: None ;
- ; ;
- ; Exit: None ;
- ; ;
- ; Alters: All registers except ES are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- ; Init - Get Horizontal Retrace Status Register Address ;
-
- FLAG_SEG EQU 40H ; Segment containing DOS flags
- VID_BASE EQU 63H ; Location of base address of video controller
-
- INIT: PUSH ES ; Save ES
- MOV AX,FLAG_SEG ; Segment containing DOS flags
- MOV ES,AX
- MOV AX,ES:VID_BASE ; Get base address of video controller
- ADD AX,6 ; Horizontal Retrace Status Register Address
- MOV RET_ADD,AX ; Save it
-
- ; Get base address of the display screen
-
- MOV WORD PTR SCREEN,MONO; Screen base for mono
- INT 11H ; Get hardware flags.
- TEST AX,10H ; See if we have a cga or monochrome
- JNZ INIT2 ; Skip if mono display
- MOV WORD PTR SCREEN,CGA; Screen base for cga
- MOV BYTE PTR CGAFLG,1 ; Set flag for cga
-
- ; Get current video mode
-
- INIT2: MOV AH,15
- INT 10H ; Get current video mode & save it
- MOV VMODE,AL ; Current video mode
- MOV VCOL,AH ; Number of columns
- MOV VPAGE,BH ; Current active video page
-
- MOV AH,3
- INT 10H ; Get cursor type or size
- MOV CURSIZE,CX ; Save it to be restored at end
-
- ; Select video mode 3, 80x25 color, alpha if CGA or mode 7 if MONO adapter
-
- MOV AX,3 ; Select video mode 3
- CMP BYTE PTR CGAFLG,0 ; 1 = CGA, 0 = MONO
- JNZ INIT4 ; Branch if CGA
- MOV AL,7 ; Select video mode 7
- INIT4: INT 10H
-
- ; Select active page 0
-
- MOV AX,500H ; Select active page 0
- INT 10H
- POP ES
-
- ; Delay to try to prevent the "screen jump" before writing to it
-
- MOV AL,3
- XOR CX,CX
- INIT5: LOOP INIT5
- DEC AL
- JNZ INIT5
-
- RET
-
- ; ;
- ;***************************************************************************;
- ; ;
- ; CURSE - Position Cursor Routine ;
- ; ;
- ; Place the block cursor at DH, DL (Row, Column - 0,0 is upper left) ;
- ; ;
- ; Entry: None ;
- ; ;
- ; Exit: None ;
- ; ;
- ; Alters: All registers are altered except AX & DX ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- CURSE: PUSH AX ; Save registers
- PUSH BX
-
- MOV AH,2 ; Set cursor position
- MOV BH,VPAGE ; Our video page
- INT 10H
-
- MOV AH,1 ; Set cursor size
- MOV CX,7 ; Starting line 0, ending line 7
- INT 10H
-
- POP BX ; Restore registers
- POP AX
- RET
-
- ; ;
- ;***************************************************************************;
- ; ;
- ; Reset The Original Video Mode And Cursor Size ;
- ; ;
- ; ;
- ; Entry: None ;
- ; ;
- ; Exit: None ;
- ; ;
- ; Alters: All registers are altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- RESET: MOV AH,0
- MOV AL,VMODE ; Restore original video mode
- INT 10H
-
- MOV AH,5
- MOV AL,VPAGE ; Restore original video page
- INT 10H
-
- MOV AH,1 ; Restore original cursor size
- MOV CX,CURSIZE ; Get original cursor size
- INT 10H
-
- RET
-
- PAGE
- ; ;
- ;***************************************************************************;
- ; ;
- ; WRITE an ASCII String On The Display ;
- ; ;
- ; Entry: ;
- ; AH = Line number (1 - 24) (if 0, start at current position) ;
- ; AL = Char position (1 - 80) (if 0, start at current position) ;
- ; SI = Offset address of the string ;
- ; The string must be terminated with a '$' ;
- ; ;
- ; Exit: ;
- ; AH points to the start of the next line ;
- ; AL points to the next char position in the line ;
- ; NXT_POS contains the next screen offset ;
- ; ;
- ; Alters: All registers except AX & SI are preserved ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- LINE EQU 160 ; Number of bytes per display line
- MLINE EQU 14 ; Highest line to use for text messages
-
- LINENO DB 0 ; Current line number-1
- CHARPOS DW 0 ; Current character position-1
-
- WRITE: PUSH DI ; Save registers
- PUSH CX
- PUSH ES
- MOV ES,SCREEN ; Get screen segment
-
- OR AH,AH ; 0 = Use pre-selected display line
- JZ W1 ; Keep same line number
- DEC AH ; Make line index of 0 - 23
- JL W8 ; Quit if too small
- CMP AH,23
- JG W8 ; Quit if too big
- MOV LINENO,AH ; Save line # -1
-
- W1: DEC AL
- JL W2 ; Neg = use pre-selected column number
- MOV BYTE PTR CHARPOS,AL; Save position -1
- W2: MOV AH,LINENO ; Get line number-1
- MOV AL,LINE ; Number of bytes in a line
- MUL AH ; Offset = (line-1) * (bytes per line)
- MOV DI,AX ; Starting offset of the line in DI
- ADD DI,CHARPOS ; Add for starting position within the line
- ADD DI,CHARPOS ; Add to account for the attribute
- MOV CX,80 ; Max length of a line
- SUB CX,CHARPOS ; Number characters to end of line
-
- W3: LODSB ; Get next character of message
- CMP AL,'$' ; Finished if '$'
- JE W8 ; Skip when finished
-
- CMP AL,CR
- JNE W4
- MOV WORD PTR CHARPOS,0
- JMP SHORT W2 ; Restart this line after CR
-
- W4: CMP AL,LF
- JNE W5 ; Skip if not LF
-
- ADD DI,LINE ; Move down one line after LF
- INC BYTE PTR LINENO
- JMP SHORT W3 ; Loop back without decrementing counter
-
- W5: CALL WRITE_ONE ; Write this character on screen
- INC DI ; Skip past attribute byte
- MOV NXT_POS,DI ; Save next screen offset position
- INC WORD PTR CHARPOS; Bump the column
- CMP WORD PTR CHARPOS,80
- JLE W6
- MOV WORD PTR CHARPOS,0
-
- W6: LOOP W3 ; Repeat for the rest of the line
-
- INC BYTE PTR LINENO
- JMP SHORT W1 ; Repeat for the rest of the lines
-
- W8: POP ES ; Restore the registers
- POP CX
- POP DI
- RET ; Return to calling routine
-
- ; ;
- ;***************************************************************************;
- ; ;
- ; WRITE_ONE Character To The Display ;
- ; ;
- ; Entry: Al = Character to write on the display screen ;
- ; DI = Offset into the display screen ;
- ; ES = Screen segment ;
- ; ;
- ; Exit: DI is incremented by one before exit ;
- ; ;
- ; Alters: Register DX is altered ;
- ; ;
- ; There is only time to write one (1) symbol during the horizontal ;
- ; retrace without creating any snow. ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- WRITE_ONE:
- PUSH AX ; Save registers
- PUSH BX
- MOV BL,AL ; Save the character to write
- MOV DX,RET_ADD ; Address of status register
-
- W_ONE1: IN AL,DX ; Read horizontal retrace status
- SHR AL,1 ; Shift bit zero into carry bit
- JC W_ONE1 ; Wait for end of horizontal retrace
-
- CLI ; Disable interrupts during write to screen
- W_ONE2: IN AL,DX ; Read horizontal retrace status
- SHR AL,1
- JNC W_ONE2 ; Wait for start of horizontal retrace
-
- MOV ES:[DI],BL ; Write the character on the display
-
- STI ; Enable interrupts after screen write
- INC DI ; Move pointer
- POP BX ; Restore registers
- POP AX
- RET
-
- ; ;
- ;***************************************************************************;
- ; ;
- ; CLRSCRN - Clear The Screen From "MLINE" Through Line 24 ;
- ; ;
- ; Entry: None ;
- ; ;
- ; Exit: None ;
- ; ;
- ; Alters: Register DX is altered ;
- ; ;
- ;***************************************************************************;
- ; ;
-
- CLRSCRN:
- PUSH AX ; Save registers
- PUSH CX
- PUSH DI
- PUSH ES
-
- MOV CX,(26-MLINE)*LINE/2 ; Number of characters to erase
- MOV DI,(MLINE-1)*LINE ; Initial offset into display screen
-
- CMP BYTE PTR CGAFLG,0
- JZ CLR1 ; Skip if mono
-
- ; Turn off the video
-
- MOV DX,RET_ADD ; Status register address (03DA hex)
- SUB DX,2 ; Mode control register (03D8 hex)
- MOV AL,1 ; 80X25 alpha color, video off
- OUT DX,AL
-
- CLR1: MOV AL,' ' ; Blank symbol
- MOV ES,SCREEN ; Set ES to screen segment
- CLR2: STOSB ; Write one blank on the display
- INC DI ; Skip past attribute byte
- LOOP CLR2 ; Loop for entire display
-
- CMP BYTE PTR CGAFLG,0
- JZ CLR3 ; Skip if MONO
-
- ; Turn on the video
-
- MOV DX,RET_ADD ; Status register address (03DA hex)
- SUB DX,2 ; Mode control register (03D8 hex)
- MOV AL,9 ; 80X25 alpha color, video on
- OUT DX,AL
-
- CLR3: POP ES ; Restore registers
- POP DI
- POP CX
- POP AX
- RET ; Return to calling routine
-
- .XLIST
- SUBTTL Messages and Data Storage
- PAGE +
- .LIST
-
- ; Messages And Data Storage
-
- HELLO DB 'LOOKMEM Interactive Memory Display Version 8/29/88$'
-
- SEGO DB CR,LF,LF,'Seg Off $'
-
- HELPMSG DB 'LOOKMEM Help : ',CR,LF
- DB 24,' Displays the next 128 bytes',CR,LF
- DB 25,' Displays the previous 128 bytes',CR,LF
- DB 16,' Increments the current segment by 10H',CR,LF
- DB 17,' Decrements the current segment by 10H',CR,LF
- DB 17,196,217,' Specify new segments or offsets',CR,LF
- DB 'Esc Exits from LOOKMEM to DOS',CR,LF
- DB 'F1 Displays this help text',CR,LF
- DB 'F2 Find a string from current seg:off',CR,LF
- DB 'F3 Find Next occurrence of same string',CR,LF,LF
- DB ' Copyright (C) John Pulliam 1988',CR,LF
- DB ' (press any key to continue)$'
- LEN_HELP EQU $ - 2 - OFFSET HELP
-
- FINDMSG DB 'FIND a hex string of up to 4 bytes starting from '
- DB 'the currently',CR,LF,'displayed segment & offset',CR,LF,LF
- DB 'Enter the hex string : __ __ __ __$'
-
- NOTFND DB 'Not Found$'
-
- CURSEG DB 'Current Segment : '
- SSTO DW 0,0
- DB '$'
-
- CUROFF DB ' Current Offset : '
- OFFSTO DW 0,0
- DB '$'
- SPACE DB ' $'
- SPACES DB ' $'
- SPACES4 DB ' $'
- COLON DB ':$'
-
- USRPROM DB 'Press Esc, ',16,', ',17,', ',24,', ',25,','
- DB ' F1 (help), F2 (find), F3 (find next), or ',17,196,217,' :$'
- LEN_PROM EQU $ - 1 - OFFSET USRPROM
- BLANKS DB LEN_PROM + 1 DUP(' '),'$'
-
- SEGMSG DB 'Enter the segment address in hex (',17,196,217,' for no '
- DB 'change) : $'
- LEN_SEGMSG EQU $ - 6 - OFFSET SEGMSG
-
- STMSG DB 'Enter the offset address in hex (',17,196,217
- DB ' for no change) : $'
- LEN_STMSG EQU $ - 6 - OFFSET STMSG
-
- ASCTOP DB ' $' ; Buffer for top line of hex display
- ASCTOP2 DB ' $' ; Buffer for top line of ASCII display
-
- CHARS DW ' ' ; Buffer for hex display
- DB ' $'
-
- ASCCHAR DB 16 DUP(' ') ; Buffer for ASCII display
-
- NXT_POS DW 0 ; Next offset position in display
-
- SEGADD DW 0 ; Segment to display (hex)
- ASCSEG DW 0,0 ; Segment to display (ASCII)
- DB ' $'
-
- OFFADD DW 0 ; Offset to display (hex)
- ASCADD DW 0,0 ; Offset to display (ASCII)
- DB ' $'
- KBUFSZ DB 0,0 ; Keyboard input buffer
- KBUF DB ' $' ; Keyboard input data, 8 ASCII symbols
- SRCHCNT DW 0
- SRCHCHR DB 0,0,0,0
-
- CSEG ENDS
- END LOOKMEM