📄 atoms.asm
字号:
mov es, st_seg ; those registers
xor al, al ; clear al
mov cx, -1 ; by using cx=-1, repnz won't stop until
repnz scasb ; it finds a match. cx will be -(length-1)
not cx ; since we use two's complement, not cx=length!
mov ax, cx ; mov length into ax, and
ret ; return
st_len ENDP
;----------------------------------------------------------------------------;
;****************************************************************************;
;----------------------------------------------------------------------------;
; ;
; BEGINNING OF SPACE TO BE USED AS DRIVER MEMORY ;
; ALL CODE AFTER ATOMLIST WILL BE ERASED BY THE DRIVER'S DATA ;
; OR BY OTHER LOADED DRIVERS ;
; ;
;----------------------------------------------------------------------------;
;****************************************************************************;
;----------------------------------------------------------------------------;
;----------------------------------------------------------------------------;
; Initialization Data and Code
; Only needed once, so after the driver is loaded and initialized it releases
; any memory that it won't use. The device allocates memory for its own use
; starting from 'AtomList'.
;----------------------------------------------------------------------------;
AtomList BYTE 0
Ident BYTE '* ATOMS Device Driver *',lf,cr,eom
Border BYTE '*********************************************',lf,cr,eom
scan_default BYTE '* Using default value of 1024 bytes *',lf,cr,eom
scan_ignore BYTE '* Ignoring extra parameters in command line *',lf,cr,eom
scan_minimum BYTE '* Minimum value of 1024 bytes will be used *',lf,cr,eom
scan_overflow BYTE '* Maximum value of 32K bytes will be used *',lf,cr,eom
HexDump BYTE '* Beginning atoms memory: '
Hex1 BYTE '0000h : '
Hex2 BYTE '0000h *',cr,lf
BYTE cr,'* Ending atoms memory: '
Hex3 BYTE '0000h *',cr,lf,eom
;----------------------------------------------------------------------------;
; Init
;----------------------------------------------------------------------------;
; routine called only once to initialize the driver. It shows the startup
; message, scans the config.sys command line, and tells MS-DOS how much memory
; it needs. Note that under DOS 5.0 the request header also tells you how
; much memory you could use.
;----------------------------------------------------------------------------;
Init PROC NEAR USES es di
@ShowStr Border ; use dos.inc macros to start the init
@ShowStr Ident ; message
INVOKE int2hex, cs, ADDR Hex1 ; get starting segment in Hex
INVOKE int2hex,MaxMem,ADDR Hex2; get starting offset in Hex
les di, [lpHeader] ; allow us to use the request values
ASSUME di:PTR REQ_HEADER ; to use the REQ_HEADER OFFSETS
; scan the config.sys command line
INVOKE scan, es:[di].cmd_off, es:[di].cmd_seg
add ax, MemEnd ; set ax to End of Memory relative to
; previous end of memory.
mov MaxMem, ax ; store the new value in MaxMem
mov es:[di].xseg,cs ; tell MS-DOS the end of our used
mov es:[di].xfer,ax ; memory (the break address)
ASSUME di:NOTHING ; di will be something else now
INVOKE int2hex, ax, ADDR Hex3 ; Get ending offset in Hex
@ShowStr HexDump ; print the Hex Dump of Memory bounds
@ShowStr Border ; show the end of our initial message
xor ax, ax ; return status OK
ret
Init ENDP
;----------------------------------------------------------------------------;
; scan
;----------------------------------------------------------------------------;
; scans the string passed by ms-dos on initialization for the amount of
; memory to allocate to the driver. Since we get a pointer to the string
; after the '=', first scan over the filename and white space, then for the
; ASCII number and turn it into decimal.
; the string we'll get might have some white space (or not) before the device
; name, then the device name, then either the end-of-line (and we'd use the
; default values) or some white space and the end-of-line (same thing) or
; some white space and a number maybe followed by some white space or the end
; of line. If there's something after the number, we'll output the extra
; parameters warning.
;
; returns: AX = number of bytes to allocate
;----------------------------------------------------------------------------;
scan PROC NEAR USES ds si, st_off:NPBYTE, st_seg:SEGPTR
LOCAL result ; result will hold the amount to allocate
mov result, 0 ; clear the result variable
mov ds, st_seg ; lodsb uses DS:SI as the source string
mov si, st_off
.REPEAT ; load from the string into the accumulator
lodsb ; while it's white space
.UNTIL ((al!=tab) && (al!=space))
; scan until we find a white space or the end
; of the line (note that we don't test the 1st
.REPEAT ; character after the spaces: it has to be a
lodsb ; letter o.w. DOS wouldn't load the driver)
.UNTIL ((al==tab) || (al==space) || (al==cr) || (al==lf))
.IF ((al==cr) || (al==lf)) ; if we found the end of line, we'll
jmp scan_d ; use the default values. jump there.
.ENDIF
.REPEAT ; scan for the next non-white space
lodsb
.UNTIL ((al!=tab) && (al!=space))
.IF ((al==cr) || (al==lf)) ; if we found the end of line, we'll
jmp scan_d ; use the default values. jump there.
.ENDIF
.REPEAT ; scan for the decimal numbers:
.IF ((al<'0')||(al>'9')); if it's not an ascii decimal number
jmp scan_i ; ignore the parameter, use defaults
.ENDIF
cbw ; set ax to 0 (by extending al to ax)
sub ax, '0' ; turn ax into a number 0-9
mov cx, ax ; save the number in cx for a while,
mov ax, result ; because ax will be used to multiply
mov bx, 10t ; 'result' by 10, to add a 'digit' to
mul bx ; the previous 'result'
jc scan_o ; if we had an overflow, i.e. result
; is more than ffffh, then use max.val
; by jumping to the overflow section.
add ax, cx ; else, add the units to the multiplied
mov result, ax ; result, and store it where it goes
lodsb
.UNTIL ((al==tab) || (al==space) || (al==cr) || (al==lf))
; when we find a space, tab, cr, or lf,
; it's not an error: we've finished
; the number scan.
.IF ((al==cr) || (al==lf)) ; if we found the end of line, we'll
jmp scan_d ; use the result value so far.
.ENDIF
.REPEAT ; skip over the white space, again
lodsb
.UNTIL ((al!=tab) && (al!=space))
.IF ((al==cr) || (al==lf)) ; if we found the end of line, we're
jmp scan_d ; fine, use the result value.
.ENDIF
; otherwise, we scanned something not
; a space or end-of-line after the
; digits, so we drop into the ignore
; warning display.
scan_i:
; we found something extra
@ShowStr scan_ignore,cs ; show the warning string
; and drop into scan_d
scan_d:
push cs ; make local data addressable (since
pop ds ; we rewrote ds in the scanner above)
.IF (result == 0) ; if we didn't scan anything into
@ShowStr scan_default ; result, show a warning that we will
mov ax, BUFMINIMUM ; use the minimum. Set ax to minimum.
.ELSEIF (result < BUFMINIMUM) ; if the result is less than the
@ShowStr scan_minimum ; minimum, display a warning and set
mov ax, BUFMINIMUM ; the buffer to the minimum
.ELSEIF (result > BUFMAXIMUM) ; if result is more than the maximum
@ShowStr scan_overflow ; display a message to inform the user
mov ax, BUFMAXIMUM ; and set the buffer to the maximum
.ELSE ; otherwise, result is acceptable
mov ax, result ; set ax to result.
.ENDIF
ret ; return
scan_o: ; overflows (request for >ffffh buffer)
mov result, BUFMAXIMUM+1 ; set ax to a value that will cause
jmp scan_d ; scan_d to print out an overflow
; message and set buffer to 32K
scan ENDP
;----------------------------------------------------------------------------;
; int2hex
; Converts a WORD into its hexadecimal representation.
; Based on Chapter 4 of the MASM Programmer's guide
;----------------------------------------------------------------------------;
; Table of hexadecimal digits
hex BYTE '0123456789ABCDEF'
int2hex PROC NEAR USES ax bx si, number:WORD, string:NPBYTE
mov bx, OFFSET hex ; load table address
mov si, string
mov ax, number ; load value to convert
shr ax, 12 ; shift right to get into table index
and ax, 0000Fh ; remove all but least-significant byte
xlat ; translate
mov [si], al ; store as last byte
mov ax, number ; load value to convert
shr ax, 8 ; shift right to get into table index
and ax, 0000Fh ; remove all but least-significant byte
xlat ; translate
mov [si+1], al ; store as third to last byte
mov ax, number ; load value to convert
shr ax, 4 ; shift right to get into table index
and ax, 0000Fh ; remove all but least-significant byte
xlat ; translate
mov [si+2], al ; store as second to last byte
mov ax, number ; load value to convert
and ax, 0000Fh ; remove all but least-significant byte
xlat ; translate
mov [si+3], al ; store as last byte in string
ret
int2hex ENDP
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -