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 + -
显示快捷键?