highload.inc
来自「Dos6.0」· INC 代码 · 共 1,910 行 · 第 1/5 页
INC
1,910 行
gxnE: stc ; In this case, we need to set the carry
jmp short gxnX ; and leave--there were no digits given.
gxnQ: dec si ; Don't read in the offensive character.
clc ; And clear carry, so they know it's okay.
gxnX: popreg <ds, cx, bx>
ret
GetXNum endp
; -----------------------------------------------------------------------------
;*** mul32 - multiplies the number in DX:AX by gnradix
; -----------------------------------------------------------------------------
; ENTRY: DX:AX = the number to be multiplied, BX = 0, gnradix = multiplier
; EXIT: DX:AX has been multiplied by gnradix if carry clear; BX still 0
; ERROR: Carry set if number was too large
; USES: Flags, AX, DX
; -----------------------------------------------------------------------------
mul32 proc near
push ax ; DX=old:hi, AX=old:lo, TOS=old:lo, BX=0
mov ax, dx ; DX=old:hi, AX=old:hi, TOS=old:lo, BX=0
mul gnradix ; DX=?, AX=new:hi, TOS=old:lo, BX=0
jc m32E ; Too big?
mov dx, ax ; DX=new:hi, AX=new:hi, TOS=old:lo, BX=0
pop ax ; DX=new:hi, AX=old:lo, TOS=orig, BX=0
xchg dx, bx ; DX=0, AX=old:lo, TOS=orig, BX=new:hi
mul gnradix ; DX=carry, AX=new:lo, TOS=orig, BX=new:hi
xchg dx, bx ; DX=new:hi, AX=new:lo, TOS=orig, BX=carry
add dx, bx ; DX=new:hi, AX=new:lo, TOS=orig, BX=carry
xor bx, bx ; DX=new:hi, AX=new:lo, TOS=orig, BX=0
ret
m32E: pop ax
ret
mul32 endp
; -----------------------------------------------------------------------------
;*** toPara - divides DX:AX by 16; result in AX only (discards extra DX data)
; -----------------------------------------------------------------------------
; ENTRY: DX:AX = the number to be divided
; EXIT: Interpereting DX:AX as bytes, AX=paragraph equivalent, 0xFFFF max
; ERROR: None
; USES: Flags, AX, DX
; -----------------------------------------------------------------------------
; Note: The 386 has a 32-bit SHR, which would work perfectly for this... but we
; can't ensure a 386 host machine. Sorry.
; -----------------------------------------------------------------------------
toPara proc near
push cx ; DX:AX=HHHH hhhh hhhh hhhh:LLLL llll llll llll
mov cl, 4 ;
shr ax, cl ; DX:AX=HHHH hhhh hhhh hhhh:0000 LLLL llll llll
xchg ax, dx ; DX:AX=0000 LLLL llll llll:HHHH hhhh hhhh hhhh
mov cl, 12
shl ax, cl ; DX:AX=0000 LLLL llll llll:hhhh 0000 0000 0000
or ax, dx ; AX=hhhh LLLL llll llll
pop cx
ret
toPara endp
ifdef DEBUG_PRTABLE
; -----------------------------------------------------------------------------
;*** PrTable - produces a printout of the variables in highvar.inc
; -- The data are reported in this format:
;
; ShrinkUMBs? (01/00) LoadAddr (DH only) UMB0 (load UMB number)
; 00 conv_used? conv_size (ignored)
; 01 umb1_used? umb1_size (00==not specified)
; 02 umb2_used? umb2_size
; ...
; 0F umb15_used? umb15_size
;
; -----------------------------------------------------------------------------
; ENTRY/EXIT : Nothing
; USES: Flags, AX
; -----------------------------------------------------------------------------
; This routine is for debugging only, and should not be included in the final
; versions of loadhigh and devicehigh (if it's called, you'll know). To use
; it, you'll need to add "include wordout.inc" if it's not available already.
; -----------------------------------------------------------------------------
public PrTable
PrTable proc near
pushreg <cx, si, ds>
dataseg ds ; Point DS into appropriate data seg
mov al, fUmbTiny
call byteout
printtab
mov ax, SegLoad
call wordout
printtab
mov al, UmbLoad
call byteout
printtab
mov al, fInHigh
call byteout
printcr
printcr
xor cx, cx ; For each entry
; ----------------------------
; PT10--CL = index into arrays
; ----------------------------
pt10: mov al, cl
call byteout
printtab
mov si, offset DS:UmbUsed ; on the UmbUsed array,
mov ax, cx
add ax, si
mov si, ax
lodsb ; Get used element
call byteout
printtab
mov si, offset DS:UmbSize ; on the UmbSize array,
mov ax, cx
shl ax, 1 ; ax *= 2 (two bytes per element)
add ax, si
mov si, ax
lodsw ; Get size element
call wordout
printcr
inc cx
cmp cx, MAXUMB
jb pt10
popreg <ds, si, cx>
normseg ds ; Return DS
ret
PrTable endp
endif ; DEBUG_PRTABLE
; -----------------------------------------------------------------------------
;*** UmbHead - returns in AX the address of the first UMB block (0x9FFF)
; -----------------------------------------------------------------------------
; ENTRY: Nothing
; EXIT: AX contains 0x9FFF for most systems
; ERROR: Carry set if pointer is 0xFFFF (if not set up yet--DH runs into this)
; USES: Flags, AX
; -----------------------------------------------------------------------------
; Early in the boot-cycle, the pointer used to obtain this value isn't set up;
; to be precise, before a UMB provider is around. In this event, the pointer
; is always set to 0xFFFF; it changes once a provider is around. On most
; machines (all of 'em I've seen), it changes to 0x9FFF at that point.
; -----------------------------------------------------------------------------
public UmbHead
UmbHead proc near
pushreg <si, ds, es>
mov ah, DOS_GET_DOS_LISTS ; Call int 21h, function 52h...
int 21h
mov ax, es:[DOS_UMB_HEAD] ; And read what's in ES:[008C]
cmp ax, 0FFFFh
jz uhE ; If it's 0xFFFF, it's an error...
clc ; Else, it isn't (CLC done by prev cmp)
jmp short uhX
uhE: stc
uhX: popreg <es, ds, si>
ret
UmbHead endp
; -----------------------------------------------------------------------------
;*** isSysMCB - sets ZF iff ES points to an MCB owned by "SC" + (8 or 9)
; -----------------------------------------------------------------------------
; ENTRY: ES:0 should point to a valid MCB
; EXIT: ZF set if owned by SC+8 or SC+9 (for japan)
; USES: Flags
; -----------------------------------------------------------------------------
isSysMCB proc near
push ax
mov ax, es:[arena_owner] ; Check the owner...
cmp ax, SystemPSPOwner ; 8 (for US OR Japan) is valid
jz ism10
cmp ax, JapanPSPOwner ; 9 (for Japan) is valid
jz ism10
jmp short ismX ; Anything else isn't.
ism10: mov ax, word ptr es:[arena_name] ; Check the name...
cmp ax, 'CS'
ismX: pop ax
ret
isSysMCB endp
; -----------------------------------------------------------------------------
;*** AddrToUmb - converts a segment address in AX to its appropriate UMB number
; -----------------------------------------------------------------------------
; ENTRY: AX contains a segment address
; EXIT: AX will contain the UMB number which contains the address (0==conv)
; ERROR: If the address is above UM Range, AX will return as FFFF.
; USES: Flags, AX
; -----------------------------------------------------------------------------
; An address in the following areas is treated as:
; 0 <-> umbhead (0x9FFF) = Conventional memory
; 0x9FFF <-> addr of first UM sys MCB = UMB #1
; ...
; addr of last UM sys MCB <-> TOM = invalid; returns #0xFFFF
; -----------------------------------------------------------------------------
AddrToUmb proc near
pushreg <cx, dx, es>
mov dx, ax ; DX = address to search for
call UmbHead ; AX = first segment
jc atuE ; If it couldn't get it, error out.
mov es, ax ; ES = first UMB segment
xor cx, cx ; Pretend we're on UMB 0 for now... (cx = UMB#)
; ----------------------------------------
; ATU10--ES - Current MCB address
; DX - Address given for conversion
; CX - Current UMB #
; ----------------------------------------
atu10: mov ax, es
cmp ax, dx ; Present segment >= given segment?
jae atuX ; Yep--done.
call isSysMCB ; Returns with ZF set if this is a system MCB
jnz atu20
inc cx ; If it _was_ a system MCB, we're in a new UMB.
atu20: mov al, es:[arena_signature]
cmp al, arena_signature_end
jz atu30 ; 'Z' means this was the last MCB... that's it.
NextMCB es, ax
jmp short atu10
; -----------------------------------------------------------------------------
; if we get to atu30, they specified a number that was past the last MCB.
; make sure it's not _inside_ that MCB before we return an error condition.
; -----------------------------------------------------------------------------
atu30: mov ax, es
add ax, es:[arena_size]
cmp ax, dx ; Present >= given?
jae atuX ; Yep! It _was_ inside.
atuE: xor cx, cx ; Else, fall through with UMB # == -1
dec cx ; (that makes it return 0xFFFF and sets CF)
atuX: mov ax, cx ; Return the UMB number in AX
popreg <es, dx, cx>
ret
AddrToUmb endp
; -----------------------------------------------------------------------------
;*** convUMB - checks after GetXNum to convert an address to a UMB number
; -- if GetXNum read a hex number, we interperete that as a segment
; address rather than a UMB number... and use that address to look up a UMB.
; This routine checks for that condition and calls AddrToUmb if necessary.
; -----------------------------------------------------------------------------
; ENTRY: AX contains a UMB number or segment, gnradix has been set by GetXNum
; EXIT: AX will contain a UMB number
; ERROR: None
; USES: Flags, AX
; -----------------------------------------------------------------------------
convUMB proc near
cmp gnradix, 16
jnz cu10 ; If it didn't read in hex, it's not an address
call AddrToUmb ; Else, convert the address to a UMB number
cmp ax, 0FFFFh
jnz cu10
inc ax ; If too high, ignore it (make it conventional)
cu10: ret
convUMB endp
; -----------------------------------------------------------------------------
;*** setUMBs - links umbs and sets allocation strategy for a load
; -- if LoadHigh, the allocation strategy MAY be LOW_FIRST instead
; of the usual HIGH_FIRST. See the code.
; -----------------------------------------------------------------------------
; ENTRY: None
; EXIT: None
; ERROR: None
; USES: Flags, fm_umb, fm_strat
; -----------------------------------------------------------------------------
setUMBs proc near
pushreg <ax, bx>
call fm_link
ifdef HV_LoadHigh
mov ax, DOS_CHECK_STRATEGY
int 21h
putdata fm_strat, al ; Store the current strategy for later restore
and ax, 007Fh ; 0000.0000.0111.1111 == All that other stuff
push ax ; Watch this carefully...
call loadLow ; returns al==0 if load low, al==1 if loadhigh
ror al, 1 ; Shift that to al==0 or al==0x80
pop bx ; ...pushed as AX above
or bl, al ; Now we have 0000.0000.?111.1111 in BX;
mov ax, DOS_SET_STRATEGY ; with ? ==1 if load highfirst. Perfect!
int 21h
endif
popreg <bx, ax>
ret
setUMBs endp
; -----------------------------------------------------------------------------
;*** loadLow - returns AL==0 if UMB0 == 0, else AL==1
; -----------------------------------------------------------------------------
; ENTRY: None
; EXIT: AL==0 if mem strategy should be set to LOW_FIRST, else AL==1
; Carry set if UMB0 not specified (_NOT_ an error)
; ERROR: None
; USES: Flags, fm_strat, fm_umb
; -----------------------------------------------------------------------------
; We want to set the memory strategy to LOW_FIRST if the user specified a
; load UMB, and it is 0. That 0 can be either from the user having _specified_
; zero (/L:0;...), or from having specified a too-big min size (/L:1,99999999)
; such that the load UMB is too small, and shouldn't be used.
; -----------------------------------------------------------------------------
loadLow proc near
push ds
dataseg ds ; Point DS into appropriate data segment
mov al, UmbLoad
cmp al, UNSPECIFIED
jnz ll10
mov al, 1 ; Return with AL==1 && STC if no UMBs specified
stc
jmp short llX
ll10: or al, al ; AL=the load UMB: Is it == 0?
jz llX ; Yep... CF==0 (from OR) && AL=0, so just exit
mov al, 1
clc
llX: pop ds ; Return DS to where it was
normseg ds ;
ret
loadLow endp
; -----------------------------------------------------------------------------
;*** HideUMBs - links UMBs and hides upper-memory as appropriate
; -----------------------------------------------------------------------------
; ENTRY: None
; EXIT: None
; ERROR: None
; USES: Flags, fm_strat, fm_umb
; -----------------------------------------------------------------------------
public HideUMBs
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?