highload.inc

来自「Dos6.0」· INC 代码 · 共 1,910 行 · 第 1/5 页

INC
1,910
字号
; -----------------------------------------------------------------------------

isSpecified	proc	near
	push	ax

	xor	bh, bh
	mov	bl, al
	getdata	al, DS:UmbUsed[bx]
	or	al, al			; Sets ZF if al==0 (ie, if unspecified)

	pop	ax
	ret
isSpecified	endp

; -----------------------------------------------------------------------------
;*** shrinkMCB - breaks an MCB into two pieces, the lowest one's size==AX
; -----------------------------------------------------------------------------
; ENTRY:    AX == new size, ES:0 == current MCB
; EXIT:     None; MCB broken if carry clear
; ERROR:    Carry set if MCB isn't as large as AX+0x20 (not a useful split)
; USES:     Flags
; -----------------------------------------------------------------------------
; If the size of the to-be-split MCB isn't at least 0x20 bytes greater than
; the specified new size, the split is useless; if it's onnly 0x10 bytes, that
; 0x10 will be used to make a header that mentions a 0-byte free space, and
; that just sucks up 0x10 bytes for nothing.  So we make 0x20 bytes the
; minimum for performing a split.
; -----------------------------------------------------------------------------

MIN_SPLIT_SIZE	equ	20h

shrinkMCB	proc	near
	pushreg	<bx, cx, es>

	mov	bx, ax			; Move things around... and
	mov	ax, es			; save this one for later.

	mov	cx, es:[arena_size]
	sub	cx, MIN_SPLIT_SIZE
	cmp	bx, cx			; {New size} vs {Current Size-20h}
	ja	smE			; if wanted_size > cur-20h, abort.

	mov	dl, es:[arena_signature]
	mov	cx, es:[arena_size]

	mov	word ptr es:[arena_size], bx
	mov	byte ptr es:[arena_signature], 'M'

	add	ax, bx
	inc	ax
	mov	es, ax			; Move to new arena area

	mov	ax, cx
	sub	ax, bx
	dec	ax			; And prepare the new size

	mov	byte ptr es:[arena_signature], dl
	mov	word ptr es:[arena_owner], 0
	mov	word ptr es:[arena_size], ax
	mov	ax, '  '
	mov	word ptr es:[arena_name+0], ax
	mov	word ptr es:[arena_name+2], ax
	mov	word ptr es:[arena_name+4], ax
	mov	word ptr es:[arena_name+6], ax

	clc
	jmp short smX

smE:	stc

smX:	popreg	<es, cx, bx>
	ret
shrinkMCB	endp

; -----------------------------------------------------------------------------
;*** hideUMB? - hides as appropriate the UMB in CL
; -----------------------------------------------------------------------------
; ENTRY:    CL should be to a valid UMB number, and AX to its address (findUMB)
; EXIT:     None; UMB is hidden as necessary
; ERROR:    None
; USES:     Flags, AX, CX
; -----------------------------------------------------------------------------
; PRIMARY LOGIC:
;
; If the UMB is specified in the DH/LH statement, then:
;    If the largest free segment is too small (check specified size), then:
;       Pretend it wasn't ever specified, and fall out of this IF.
;    Else, if largest free segment is LARGER than specified size, then:
;       If /S was given on the command-line, then:
;          Break that element into two pieces
;          Set a flag that we're shrinking
;       Endif
;    Endif
; Endif
; If the UMB is NOT specified (or was removed by the above):
;    Hide all free elements in the UMB
;    If the flag that we're shrinking was set, then:
;       UN-hide the lower portion of the shrunken UMB
;    ENDIF
; ENDIF
; -----------------------------------------------------------------------------

hideUMB?	proc
	pushreg	<bx, dx, es>

	mov	al, cl
	call	isSpecified	; Returns ZF set if al's umb was NOT specified
	jz	hu?20

	mov	al, cl		; Retrieve the size of the largest
	call	BigFree		; free element in AX; put its address in ES
	jc	hu?20		; Oops.  Errors mean skip this part.

	push	ax		; TOS==size of BigFree in UMB (popped as BX)
	mov	al, cl		; Retrieve the user's specified
	call	GetSize		; minimum size for this umb (into AX)
	pop	bx		; Now BX==BigFree, AX==Specified Size

	or	ax, ax		; If they didn't specify one,
	jz	hu?20		; Skip over all this.

	cmp	ax, bx		; Ah... if (specified > max free)
	jbe	hu?10

	mov	al, cl		;    Then mark that UMB as unused.  Nya nya.
	call	unMarkUMB
	jmp short hu?20

hu?10:	call	isTiny		; Returns ZF clear if user specified /S
	jz	hu?20

	call	shrinkMCB	; They specified /S, so shrink the MCB to AX
	jc	hu?20		; Ah... if didn't shrink after all, skip this:

	mov	dx, es
	jmp short hu?30		; Skip the spec check.. we wanna hide this one.

hu?20:	mov	ax, cx
	call	isSpecified	; If they specified this UMB, we're done...
	jnz	hu?X		; so leave.

	xor	dx, dx

hu?30:	mov	al, cl

	call	hideUMB		; Hides everything in UMB #al

	or	dx, dx		; Did we shrink a UMB?  If not, DX==0,
	jz	hu?X		; So we should leave.

	mov	es, dx		; Ah, but if it isn't, DX==the MCB's address;
	call	unHideMCB	; Un-hides the lower portion of that MCB.

hu?X:	popreg	<es, dx, bx>
	ret
hideUMB?	endp

; -----------------------------------------------------------------------------
;*** UnFreeze - Marks FROZEN elements as FREE
; -----------------------------------------------------------------------------
; Entry:  None
; Exit:   None; all 8+FROZEN elements are marked as FREE, from any UMB.
; Error:  None
; Uses:   Flags
; -----------------------------------------------------------------------------

	public  UnFreeze

UnFreeze	proc	near
	pushreg	<ax, es>

	call	UmbHead		; Returns with carry if err, else ES == MCB
	jc	ufX

	mov	es, ax

; ------------------------------
; UF10--ES - Current MCB address
; ------------------------------

uf10:	call	isFrozMCB	; Returns with ZF set if MCB is FROZEN
	jnz	uf20
	call	unHideMCB

uf20:	mov	al, es:[arena_signature]

	cmp	al, arena_signature_end
	jz	ufX		; 'Z' means this was the last MCB... that's it.

	NextMCB	es, ax		; Go on forward.
	jmp short uf10

ufX:	popreg	<es, ax>
	ret
UnFreeze	endp

; -----------------------------------------------------------------------------
;*** isFrozMCB - returns with ZF set if current MCB (ES:0) is FROZEN
; -----------------------------------------------------------------------------
; ENTRY:    ES:0 should point to an MCB
; EXIT:     ZF set if MCB is frozen, else !ZF
; ERROR:    None
; USES:     Flags
; -----------------------------------------------------------------------------

isFrozMCB	proc	near
	push	ax

	mov	ax, es:[arena_owner]	; Check the owner...
	cmp	ax, SystemPSPOwner	; 8 (for US OR Japan) is valid
	jnz	ifmX

	mov	ax, word ptr es:[arena_name]
	cmp	ax, 'RF'
	jnz	ifmX
	mov	ax, word ptr es:[arena_name+2]
	cmp	ax, 'ZO'
	jnz	ifmX
	mov	ax, word ptr es:[arena_name+4]
	cmp	ax, 'NE'
	jnz	ifmX
	mov	ax, word ptr es:[arena_name+6]
	cmp	ax, '  '

ifmX:	pop	ax
	ret
isFrozMCB	endp

; -----------------------------------------------------------------------------
;*** frezMCB - marks as 8+FROZEN the MCB at ES:0
; -----------------------------------------------------------------------------
; ENTRY:    ES:0 should point to an MCB
; EXIT:     None; MCB frozen
; ERROR:    None
; USES:     None
; -----------------------------------------------------------------------------

frezMCB	proc	near
	mov	es:[arena_owner], SystemPSPOwner
	mov	word ptr es:[arena_name+0], 'RF'
	mov	word ptr es:[arena_name+2], 'ZO'
	mov	word ptr es:[arena_name+4], 'NE'
	mov	word ptr es:[arena_name+6], '  '
	ret
frezMCB	endp

; -----------------------------------------------------------------------------
;*** FreezeUM - Marks FROZEN all UM elements now FREE, save those in load UMB
; -----------------------------------------------------------------------------
; Entry:  None
; Exit:   None; all free elements not in load UMB marked as 8+FROZEN
; Error:  None
; Uses:   Flags
; -----------------------------------------------------------------------------

FreezeUM	proc	near
	pushreg	<ax, cx, dx, es>

	call	GetLoadUMB
	xor	ah, ah		; Zap ah, so al==ax
	mov	dx, ax		; Store the load UMB in DX, so we can skip it

	call	UmbHead		; Returns first UMB segment in AX
	mov	es, ax
	xor	cx, cx		; Pretend we're on UMB 0 for now...

; -----------------------------------------
; FUM10--ES - Current MCB address
;        CX - Current UMB number
;        DX - UMB number to skip (load UMB)
; -----------------------------------------

fum10:	call	isSysMCB	; Returns with ZF set if owner is SYSTEM
	jnz	fum20

	inc	cx		; If it _was_ SYSTEM, we're in a new UMB.

fum20:	cmp	cx, dx		; If this is the load UMB, we don't want to
	jz	fum30		; freeze anything... so skip that section.

	call	isFreeMCB	; Oh.  If it's not free, we can't freeze it
	jnz	fum30		; either.

	call	frezMCB

fum30:	mov	al, es:[arena_signature]
	cmp	al, arena_signature_end
	jz	fumX		; 'Z' means this was the last MCB... that's it.

	NextMCB	es, ax		; Go on forward.
	jmp short fum10

fumX:	popreg	<es, dx, cx, ax>
	ret
FreezeUM	endp

; -----------------------------------------------------------------------------
;*** UmbTest - returns with carry set if UMBs are not available, else CF==false
; -----------------------------------------------------------------------------
; ENTRY:    None
; EXIT:     Carry is clear if UMBs are available, or set if they are not
; ERROR:    None
; USES:     CF (AX,BX,DS,ES pushed 'cause they're used by others)
; -----------------------------------------------------------------------------

	public	UmbTest

UmbTest	proc	near
	pushreg	<ax, bx, ds, es>

	call	fm_link			; Link in UMBs (if not already linked)
	call	WalkMem			; Check to see if they're really linked
	pushf				; And remember what we found out
	call	fm_unlink		; Unlink UMBs (if WE have linked 'em)
	popf				; And restore what we found out.

	popreg	<es, ds, bx, ax>
	ret
UmbTest	endp

; -----------------------------------------------------------------------------
;*** WalkMem - travels memory chain and returns carry clear iff UMBs are linked
; -----------------------------------------------------------------------------
; ENTRY:    None
; EXIT:     Carry SET if MCB chain stops before 9FFF, CLEAR if stops >= 9FFF.
; ERROR:    None
; USES:     Flags
; -----------------------------------------------------------------------------

WalkMem	proc	near
	pushreg	<ax, bx, es>

	mov	ah, DOS_GET_DOS_LISTS	; Call int 21h, function 52h...
	int	21h

	mov	ax, es:[bx -2]
	mov	es, ax

; ------------------------------
; UM10: ES = Current MCB pointer
; ------------------------------

um10:	mov	al, es:[arena_signature]
	cmp	al, arena_signature_end
	jz	um20			; If signature == 'Z', hay no more.

	NextMCB	es, bx			; Move to the next MCB
	jmp short um10			; And restart the loop.

um20:	mov	ax, es
	cmp	ax, 9FFFh		; This sets CF iff ax < 9FFF.

	popreg	<es, bx, ax>
	ret
WalkMem	endp

; -----------------------------------------------------------------------------
;*** hl_unlink - unlinks UMBs if fm_umb is set to 0; restores strategy too
; -----------------------------------------------------------------------------
; ENTRY:    fm_umb == 1 : leave linked, else unlink
; EXIT:     None
; ERROR:    None
; USES:     AX, BX
; -----------------------------------------------------------------------------

hl_unlink	proc	near
	xor	bh, bh
	getdata	bl, fm_umb		; Restore original link-state
	mov	ax, DOS_SET_UMBLINK
	int	21h

ifdef HV_LoadHigh
	xor	bh, bh
	getdata	bl, fm_strat		; Restore original mem-alloc strategy

	mov	ax, DOS_SET_STRATEGY
	int	21h
endif
	ret
hl_unlink	endp

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?