highload.inc
来自「Dos6.0」· INC 代码 · 共 1,910 行 · 第 1/5 页
INC
1,910 行
cmp al, optS ; just read 'S'?
jnz pv30
call incArgc ; If it's /S, it's another arg for LH to skip.
putdata fUmbTiny, 1 ; /S, so ES:SI==" /L..." or " module opts", or
jmp short pv10 ; possibly even "/L...".
pv30: cmp al, optL ; If it's not 'L' either, then 'tis a bad
jnz pvE1 ; switch!
call incArgc ; If it's /L, it's another arg for LH to skip.
call parseL
jnc pv10 ; If no carry, go back and look for more
dec si ; Else, back up and exit.
jmp short pvErr ; AX has already been set by parseL
pvE1: mov ax, PV_InvSwt ; Unrecognized switch passed
pvErr: dec si
dec si
stc
pvX: popreg <es, ds, di>
ret
ParseVar endp
; -----------------------------------------------------------------------------
;*** parseL - parses ":nnnn[,nnnn][;nnnn[,nnnn]]*" for ParseVar
; -----------------------------------------------------------------------------
; ENTRY: ES:SI points to colon
; EXIT: ES:SI points to first character not parsed
; ERROR: Carry set; rewind three characters and return (see ParseVar)
; USES: ES:SI, flags, AX, CX, DX, variables in highvar.inc
; -----------------------------------------------------------------------------
; If the string here is terminated with anything other than whitespace or a
; switchchar (perhaps it's /S or another /L:... ), then we return with carry
; set, indicating that they've screwed up the syntax. The 3-character rewind
; makes sure the app /L: is reported as being the culprit.
; -----------------------------------------------------------------------------
parseL proc near
lodsb
cmp al, ':' ; Make sure they did /L:
jnz plE1 ; If they didn't, return with carry set.
; ------------------------------------------
; PL10--ES:SI = a UMB number, after /L: or ;
; ------------------------------------------
pl10: call GetXNum ; After this, 'tis ",size" or ";umb" or " mod"
jc plE2 ; And error if it's a bad number.
call convUMB ; Convert any address to a UMB number
mov cl, al ; Remember the UMB number
call stowUMB ; Mark this UMB # as used;
jc plE2 ; If it was already marked, it'll error
call incArgc ; Each UMB number is another arg for LH to skip
lodsb
cmp al, ';' ; Did "umb;" ?
jz pl10 ; Yep: go back and get another UMB.
call isWhite ; Did "umb " ?
jz plX ; Yep: return (it'll go back to whitespace)
call isEOL ; Did "umb" ?
jz plSwX ; If so, backup and exit like everything's ok
cmp al, SWTCH ; Did "umb/" ? (as in, "/L:1,100;2/S")
jz plSwX ; If so, back up ES:SI one character and return
cmp al, ',' ; Did "umb," ?
jnz plE1 ; Just what the heck DID they do? Return error.
; --- Read a size -------------------------------------------------------------
call GetXNum ; Stop on "size;" or "size " or anything else
jc plE1 ; And error if it's a bad size.
call toPara ; Convert from bytes to paragraphs
call stowSiz ; CL still has the UMB number for this routine
call incArgc ; Each UMB size is another arg for LH to skip
lodsb
cmp al, ';' ; They did "umb,size;", so get another UMB.
jz pl10 ;
call isWhite ; Did it end with whitespace?
jz plX ; If so, we're done here--go back.
call isEOL ; Did they do "umb,size" and end??? (stupid)
jz plSwX ; If so, backup and exit like everything's ok
cmp al, SWTCH ; Did they do "umb,size/" ?
jz plSwX ; If so, again, we're done here.
plE1: mov ax, PV_InvArg ; If not, we don't know WHAT they did...
dec si
stc
ret
plE2: mov ax, PV_BadUMB ; In this case, they've specified a UMB twice
stc
ret
plSwX: dec si ; If we hit a '/' character, back up one char
; so the whitespace checker will see it too.
plX: clc ; Then just return with carry clear, so
ret ; ParseVar will go about its business.
parseL endp
; -----------------------------------------------------------------------------
;*** incArgc - increments fm_argc, for use with LoadHigh command-line parsing
; -----------------------------------------------------------------------------
; ENTRY: None
; EXIT: None
; ERROR: None
; USES: fm_argc, flags
; -----------------------------------------------------------------------------
incArgc proc near
push ax
getdata al, fm_argc ; Obtain previous value of fm_argc,
inc al ; Increment it,
putdata fm_argc, al ; And store it right back.
pop ax
ret
incArgc endp
; -----------------------------------------------------------------------------
;*** isEOL - returns with ZF set iff AL contains CR or LF, or 0
; -----------------------------------------------------------------------------
; ENTRY: AL contains character to test
; EXIT: ZF set iff AL contains CR or LF, or 0
; ERROR: None
; USES: ZF
; -----------------------------------------------------------------------------
isEOL proc near
cmp al, 0 ; Null-terminator
jz ieX
cmp al, CR ; Carriage Return
jz ieX
cmp al, LF ; LineFeed
ieX: ret
isEOL endp
; -----------------------------------------------------------------------------
;*** isWhite - returns with ZF set iff AL contains whitespace (or "=")
; -----------------------------------------------------------------------------
; ENTRY: AL contains character to test
; EXIT: ZF set iff AL contains space, tab, or equals
; ERROR: None
; USES: ZF
; -----------------------------------------------------------------------------
isWhite proc near
cmp al, ' ' ; Space
jz iwX
cmp al, '=' ; Equals (treat as whitespace)
jz iwX
cmp al, TAB ; Tab
iwX: ret
isWhite endp
; -----------------------------------------------------------------------------
;*** unMarkUMB - marks a given UMB as unused, even if previously marked used
; -----------------------------------------------------------------------------
; ENTRY: AL contains UMB number
; EXIT: None
; ERROR: None
; USES: Flags, variables in highvar.inc
; -----------------------------------------------------------------------------
unMarkUMB proc near
pushreg <ax, bx, di, es>
dataseg es
xor ah, ah
mov bx, ax
mov es:UmbUsed[bx], 0
cmp UmbLoad, al
jnz umu10
mov UmbLoad, 0 ; If unmarked the load UMB, load into convent.
umu10: popreg <es, di, bx, ax>
normseg es
ret
unMarkUMB endp
; -----------------------------------------------------------------------------
;*** stowUMB - marks a given UMB as used, if it hasn't been so marked before
; -- accepts a UMB # in AL, and makes sure it hasn't yet been
; listed in the /L:... chain. If it's the first one specified, it sets UmbLoad
; to that UMB #... and in any case, it marks the UMB as specified.
; -----------------------------------------------------------------------------
; ENTRY: AL contains UMB number, as specified by the user
; EXIT: None
; ERROR: Carry set if UMB # is less than 0 or >= MAXUMB (see highvar.inc)
; USES: AX, Flags, variables in highvar.inc
; -----------------------------------------------------------------------------
stowUMB proc near
cmp al, MAXUMB
jb su10
stc
ret ; Ooops-- UMB>=MAXUMB
su10: pushreg <bx, di, si, ds, es>
dataseg es ; Point ES into appropriate data segment
dataseg ds ; Point DS into appropriate data segment
cmp UmbLoad, UNSPECIFIED ; If this, we haven't been here before
jne su20
mov UmbLoad, al ; So remember this UMB as the load UMB slot.
su20: or al, al ; If they gave UMB 0, there's really nothing
jz su30 ; that we should do here.
mov bl, al
xor bh, bh
mov ax, 1 ; Now, AX = 1, and BX = UMB Number
xchg ES:UmbUsed[bx], al
or al, al ; If it was already 1, then al==1... and that
jz su30 ; means an error.
stc ; OOOPS! This one's been used before. :(
su30: popreg <es, ds, si, di, bx>
normseg ds
normseg es
ret
stowumb endp
; -----------------------------------------------------------------------------
;*** stowSiz - marks a given UMB as having a given minimum size
; -----------------------------------------------------------------------------
; ENTRY: CL contains UMB number, AX contains size
; EXIT: None
; ERROR: None
; USES: AX, DX, Flags, variables in highvar.inc
; -----------------------------------------------------------------------------
stowSiz proc near
pushreg <bx, di, es>
dataseg es ; Point ES into appropriate data seg
mov bl, cl ; Now bl==UMB number, AX==size
mov bh, 0 ; bx==UMB number, AX==size
shl bl, 1 ; bx==offset into array, AX=size
mov es:UmbSize[bx], ax ; Store the size
popreg <es, di, bx>
normseg es ; Return ES to where it was
ret
stowSiz endp
; -----------------------------------------------------------------------------
;*** toDigit - converts a character-digit to its binary counterpart
; -- verifies that CL contains a valid character-digit; if so, it
; changes CL to its counterpart binary digit ((CL-'0') or (CL-'A'+10)). A-F
; are considered valid iff gnradix is 16.
; -----------------------------------------------------------------------------
; ENTRY: CL contains a digit ('0' to '9' or, if gnradix==16, 'A' to 'F')
; EXIT: CL contains digit in binary (0 to 9 or, if gnradix==16, 0 to 15)
; ERROR: Carry set indicates invalid digit; carry clear indicates good digit
; USES: CL, Flags
; -----------------------------------------------------------------------------
; If the string is preceeded with "0x", the value is read as hexadecimal; else,
; as decimal. After a read, you may check the radix by examining gnradix--it
; will be 10 or 16.
; -----------------------------------------------------------------------------
public gnradix
gnradix dw ? ; Must be a word--16x16 multiplication
toDigit proc near
cmp gnradix, 16
jnz td20 ; Don't check hex digits if radix isn't 16
cmp cl, 'a'
jb td10
cmp cl, 'f'
ja tdE ; Nothing valid above 'z' at all...
sub cl, 'a'-10 ; Make 'a'==10 and return.
; clc ; <- CLC is implicit from last SUB
ret
td10: cmp cl, 'A'
jb td20 ; Below 'A'? Not a letter...
cmp cl, 'F'
ja tdE ; Above 'F'? Not a digit.
sub cl, 'A'-10 ; Make 'A'==10 and return.
; clc ; <- CLC is implicit from last SUB
ret
td20: cmp cl, '0' ; If less than zero,
jb tdE ; Done.
cmp cl, '9' ; Or, if greater than nine,
ja tdE ; Done.
sub cl, '0' ; Okay--make '0'==0 and return.
; clc ; <- CLC is implicit from last SUB
ret
tdE: stc
ret
todigit endp
; -----------------------------------------------------------------------------
;*** GetXNum - reads a 32-bit ASCII number at ES:SI and returns it in DX:AX
; -----------------------------------------------------------------------------
; ENTRY: ES:SI points to an ascii string to scan
; EXIT: ES:SI moved to first invalid digit, DX:AX contains value read
; ERROR: Carry set if # is too big, or has no digits (EOL possibly)
; USES: ES:SI, DX, AX, Flags, gnradix
; -----------------------------------------------------------------------------
; If the string is preceeded with "0x", the value is read as hexadecimal; else,
; as decimal. After a read, you may check the radix by examining gnradix--it
; will be 10 or 16.
; -----------------------------------------------------------------------------
public GetXNum
GetXNum proc near
pushreg <bx, cx, ds>
cld
xor ax, ax
xor bx, bx
xor cx, cx
xor dx, dx ; Start with 0 (makes sense)
mov gnradix, 10 ; And default to a radix of 10 (dec)
mov cl, byte ptr es:[si] ; Now AX=0, BX=0, CH=0/CL=char, DX=0
call toDigit
jc gxnE ; If it's not a digit, leave now.
or cl, cl
jnz gxn20 ; Doesn't have '0x'
mov cl, byte ptr es:[si+1]
cmp cl, 'x' ; Either 'x'...
jz gxn10
cmp cl, 'X' ; ...or 'X' means it's hexadecimal
jnz gxn20
gxn10: mov gnradix, 16
inc si ; Since we read "0x", march over it.
inc si
; ------------------------------------------------------
; GXN20--ES:SI = a digit in a number; if not, we're done
; DX:AX = current total
; BX = 0
; CH = 0
; ------------------------------------------------------
gxn20: mov cl, byte ptr es:[si] ; Now DX:AX=current total, CH=0/CL=char
inc si
call toDigit ; Accepts only valid digits, A-F -> 10-16
jc gxnQ ; <- Ah... wasn't a digit. Stop.
call mul32 ; Multiply DX:AX by gnradix
jc gxnX ; (if it's too big, error out)
add ax, cx ; Add the digit
adc dx, bx ; (BX is 0!)--Adds 1 iff last add wrapped
jc gxnX ; If _that_ wrapped, it's too big.
jmp short gxn20
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?