himem2.asm

来自「Dos6.0」· 汇编 代码 · 共 2,333 行 · 第 1/4 页

ASM
2,333
字号

GPZSwitch:				; /Z switch

	mov	cs:[pfnEnabA20],  offset _text:LocalEnableA20
	mov	cs:[pfnDisabA20], offset _text:LocalDisableA20

	ret				; (CY already clear)

;---------------------------------------
;	Process /A20CONTROL: parameter

GPGotA20Control:
	mov	ax,word ptr [StringParm]
	or	ax,2020h
	mov	bl,0FFh
	cmp	ax,'no' 		; ON ?	- means we take control
	jz	GPSetA20
	inc	bl
	cmp	ax,'fo' 		; OFF ? - means we leave alone if on
	jz	GPSetA20

GPBadParmRet:				; common failure exit
	stc
	ret

GPSetA20:
	mov	fA20Control,bl		; Z if A20 should be left alone if
					;   it's already on when we're loaded

GPGoodParmRet:				; common success exit
	clc
	ret

;---------------------------------------
;	Process /MACHINE: parameter.

GPGotMachine:
	push	si				; save current location
	push	ds				;    in param string

	push	cs
	pop	ds
	mov	di,offset _text:MachineName	; es:di -> MachineName

GPNextTbl:
	xor	bx,bx

GPNextName:
	mov	si,offset _text:StringParm	; ds:si -> StringParm

GPChkNext:
	cmp	byte ptr es:[di],0FFh		; end of name table?
	jz	GPNoName

	lodsb				; char from StringParm
	cmp	al,'A'			; force to lower case for match
	jb	@f			; (might be numeric, so don't just OR)
	cmp	al,'Z'
	ja	@f
	or	al,20h
@@:
	cmp	al,es:[di]		; match so far?
	jnz	GPFlushName

	or	al,al			; finished if matched up to & incl NULL
	jz	GPFoundName

	inc	di			; still matches, check next char
	jmp	short GPChkNext

GPFlushName:
	inc	bx
GPFN2:
	inc	di
	cmp	byte ptr es:[di],0FFh
	jz	GPNoName

	cmp	byte ptr es:[di],0
	jnz	GPFN2
	inc	di
	jmp	short GPNextName

GPFoundName:
	mov	cs:[MachineNum],bx	; found a match, remember which entry
	jmp	short GPNameDone	;   it is for later

GPNoName:

	cmp	di,offset _text:AltNameTbl
	ja	GPBadName
	mov	di,offset _text:AltNameTbl
	jmp	short GPNextTbl

GPNameDone:
	pop	ds			; recover parm line pointer
	pop	si
	jmp	GPGoodParmRet

GPBadName:
	pop	ds			; clear stack and error out...
	pop	si
	jmp	GPBadParmRet

;---------------------------------------
;	Process /NUMHANDLES= parameter.

GPGotHands:
	cmp	dx,MAXHANDLES
	jna	@f
	jmp	GPBadParmRet
@@:
	or	dx,dx		; Zero?
	jnz	@f
	jmp	GPBadParmRet
@@:
	push	es
	mov	es,hiseg
	assume	es:funky
	mov     [cHandles],dx ; Store it
	pop	es
	assume	es:nothing

	mov	fNumHandSet, 0FFh

	jmp	GPGoodParmRet

;---------------------------------------
;	 Process /HMAMIN= parameter

GPGotMin:
	cmp	dx,64
	jna	@f
	jmp	GPBadParmRet
@@:
	mov	cl,10		; Convert from K to bytes
	shl	dx,cl
	mov	cs:[MinHMASize],dx
	mov	fHMAminSet, 0FFh
	jmp	GPGoodParmRet


;---------------------------------------
;	Process /SHADOWRAM: parameter

GPGotShadow:
	mov	ax,word ptr [StringParm]
	or	ax,2020h
	xor	bl,bl
	cmp	ax,'no' 		; ON ?	- means we leave it alone
	jz	GPSetShadow
	inc	bl
	cmp	ax,'fo' 		; OFF ? - means we turn it off
	jz	GPSetShadow
	jmp	GPBadParmRet

GPSetShadow:
	mov	fShadowOff,bl		; NZ if Shadow RAM should be turned off
	jmp	GPGoodParmRet


;---------------------------------------
;	Process /CPUCLOCK: parameter

GPGotCPUClock:

	mov	ax,word ptr [StringParm]
	or	ax,2020h
	xor	bl,bl
	cmp	ax,'fo' 		; OFF ? - means we don't worry about it
	jz	GPSetClock
	inc	bl
	cmp	ax,'no' 		; ON ?	- means we preserve CPU clock
	jz	GPSetClock		;	  rate
	jmp	GPBadParmRet

GPSetClock:
	mov	fCPUClock,bl		; NZ if clock rate preserved
	jmp	GPGoodParmRet


;---------------------------------------
;	Process /INT15= parameter

GPGotInt15:
	cmp	dx, 64			; atleast 64K
	jae	@f
	jmp	GPBadParmRet
@@:	call	GetInt15Memory
	cmp	ax, dx			; enuf Ext Mem ?
	jae	@f
	jmp	GPBadParmRet
@@:	mov	[Int15MemSize], dx
	jmp	GPGoodParmRet


GPDoParameters	endp


;*----------------------------------------------------------------------*

; Get the next character from DS:SI, set CY if it's an EOL (CR, LF), set
; Z if it's a space

GPOffEOL	dw	-1

	public	GPGetChar

GPGetChar	proc	near

	cmp	si,cs:[GPOffEOL]	; are we already at EOL?
	jnb	GPAtEOL

	lodsb				; no, get next char
	cmp	al,10			; is this the EOL?
	je	GPHitEOL
	cmp	al,13
	je	GPHitEOL

	cmp	al,' '			; set Z if blank

	clc
	ret

GPHitEOL:
	mov	cs:[GPOffEOL],si	; save EOL offset once
GPAtEOL:
	stc
	ret

GPGetChar	endp


;*----------------------------------------------------------------------*

;  Print user msgs now instead of while processing so they can be
;  suppressed if /V (verbose) doesn't appear on command line.

GPPrintInfo proc   near

	; /NUMHANDLES=

	cmp	fNumHandSet, 0
	je	GPPI_HMAMin

	mov	dx,offset StartMsg ; display descriptive message
	call    GPPrintIt

	push	es
	mov	es,hiseg
	mov	ax,es:[cHandles]
	pop	es

	call    GPPrintAX
	mov	dx,offset HandlesMsg
	call	GPPrintIt

GPPI_HMAMin:

	; /HMAMIN=

	cmp	fHMAminSet, 0
	je	GPPI_exit

	mov	dx,offset HMAMINMsg ; print a descriptive message
	call    GPPrintIt
	mov	ax,cs:[MinHMASize]
	mov	cl, 10			; convert from bytes to k
	shr	ax, cl
	call    GPPrintAX
	mov	dx,offset KMsg
	call    GPPrintIt

GPPI_exit:
	ret

GPPrintInfo endp

;*----------------------------------------------------------------------*

GPPrintIt   proc    near

	push    ds		; Save current DS
	push    cs		; Set DS=CS
	pop	ds
	call	DispInfoMsg
	pop	ds		; Restore DS
	ret

GPPrintIt   endp

;*----------------------------------------------------------------------*

GPPrintAX   proc    near

	mov	cx,10
	xor	dx,dx
	div	cx
	or	ax,ax
	jz	GPAPrint
	push    dx
	call    GPPrintAX
	pop	dx
GPAPrint:
	add	dl,'0'
	call	DispInfoChar
	ret

GPPrintAX   endp

;*----------------------------------------------------------------------*
;*									*
;*  InitHandles -							*
;*									*
;*	Initialize the Extended Memory Handle Table			*
;*									*
;*  ARGS:   None							*
;*  RETS:   None							*
;*  REGS:   AX, BX, CX, and Flags are clobbered				*
;*									*
;*----------------------------------------------------------------------*

	assume	ds:_text

	public	InitHandles

InitHandles proc    near
	push	es
	mov	es,hiseg
	assume	es:funky
	mov	cx,[cHandles]

;	Init the Handle table.

	mov	bx,[KiddValley]

	xor	ax,ax
IHTabLoop:
	mov	[bx].Flags,UNUSEDFLAG
	mov	[bx].cLock,al
	mov	[bx].Base.lo,ax
	mov	[bx].Base.hi,ax
	mov	[bx].Len.lo,ax
	mov	[bx].Len.hi,ax
	if	keep_cs
	mov	[bx].Acs,ax
	endif
	add	bx,SIZE Handle
	loop    IHTabLoop

	mov	[KiddValleyTop],bx	; save top for handle validation
	pop	es
	assume	es:nothing
	ret

InitHandles endp


;*----------------------------------------------------------------------*
;*									*
;*  ScanEISA - poll any EISA devices through the BIOS's Int15(0d8h)	*
;*     and add any memory we find out about to our free memory table.	*
;*     Note:  this code (including a big buffer) gets thrown out after	*
;*     completion of the initialization sequence.			*
;*									*
;*	Note:  The COMPAQ BIOS uses up 1.5K of stack during int15(d80x) *
;*		so we'll set up a separate stack while we're here	*
;*									*
;*----------------------------------------------------------------------*

save_ss	dw	0
save_sp	dw	0

	public	ScanEISA

ScanEISA	proc	near
	assume	ds:_text

	mov	save_ss,ss
	mov	save_sp,sp
	push	cs
	pop	ss
	mov	sp,offset EISA_stack

	xor	cl,cl			; start with slot zero

SEISA_01:
	push    cx			; save slot number
	mov	ax,0d800h		; get summary of configuration
	int	15h
	pop	cx			; restore slot number
	jc	SEISA_09		;  skip if any kind of error
	test    dl,2			; does that slot have any memory?
	jz	SEISA_09		;  skip if not
	cmp	dh,0			; zero functions would be an
	jz	SEISA_09		;  error condition
	mov	ch,dh			; copy function number to ch

;	Now we've found a valid slot with some memory.  Let's find out
;	  what kind of memory it is, where its located, and how much there is.

SEISA_02:
	push    cx			; save slot and function
	mov	ax,0d801h		; read function information
	lea	si,EISABuffer		; pass pointer to our buffer
	int	15h
	jc	SEISA_04		; brif any error

;	Now look into buffer for memory information

	test    byte ptr EISA_FncInfo,80h ; function disabled?
	jnz	SEISA_04		;  brif so
	test    byte ptr EISA_FncInfo,2	; memory information follows?
	jz	SEISA_04		;  done if not

	lea	si,EISA_MemConfig	; point to memory information
SEISA_03:

; M007
	mov	al, ds:byte ptr [si]
	and	al, 079h
	cmp	al, 1			; Make sure that Reserved bit = 0
					;		 Shared bit   = 0
					;		 memory type = SYSTEM
					;		 Read/Write  = TRUE
	jne	SEISA_03a		; (See EISA spec for bit definitions)
; M007

	mov	cx,ds:word ptr 2[si]    ; get base address in 256 bytes
	mov	bl,ds:byte ptr 4[si]    ;  get highest byte
	xor	bh, bh
	mov	al,cl			; save lowest bits for later
	shr	bl,1			; convert to our internal 1k format
	rcr	cx,1
	shr	bl,1
	rcr	cx,1
	test    al,3			; was base not on a 1k boundary?
	mov	ax,ds:word ptr 5[si]    ; get length in k
	jz	SEISA_03b		;  brif base was on 1k boundary
	dec	ax			; sacrifice the partial k
	add	cx,1			; and bump base to first complete k
	adc	bx,0
SEISA_03b:
	xor	dx, dx
	or	ax, ax
	jnz	@f
	inc	dx
@@:
	push    si
	cmp	cx,1024			; is it below a meg?
	jb	seisa_0xx		; ignore it if so
ifdef WIN30COMPATIBLE				;M005
	or	bx, bx
	jnz	seisa_0xx
	cmp	cx,1024*16		; is it above 16 meg?
	jae	seisa_0xx		; ignore it if so
endif                                           ;M005
	mov	di, pAddMem
	push	cs
	call	call_hi_in_di		; add that memory to our tables
seisa_0xx:
	pop	si
SEISA_03a:
	add	si,7			; next entry
	test    ds:byte ptr -7[si],80h  ;  was that the last one?
	jnz	SEISA_03		;  loop if not
SEISA_04:
	pop	cx			; restore slot and function
	dec	ch			; next lower function
	jnl	SEISA_02		; valid functions are 0..n

SEISA_09:
	inc	cl			; next slot
	cmp	cl,16
	jae	@f
	jmp	SEISA_01
@@:

; Now check for EISA memory and Int 15h/88h overlap.  In the default case
; we'll ignore any EISA blocks starting at 1Meg under the assumption that
; this memory will be claimed later via the Int 15h hook.  If the Int 15h/88h
; call indicates less memory than the EISA scan, it may be that an Int 15h
; allocator has been loaded before us, and if we just grabbed all EISA
; memory starting at 1Meg, we would stomp all over them.  On the other hand,
; a number of BIOS' never return > 15 (16?) meg of extended memory via Int 15h
; (even if there is much more memory installed), so we provide the /EISA
; command line parameter to override this default and allow himem to steal
; all EISA memory.  If the /EISA switch is used, there better not be any
; Int 15h allocators loaded before himem!

;	Locate a free memory block in the handle table at 1 Meg (1024k)

	push	es
	mov	es,hiseg
	assume	es:funky
	mov	bx,[KiddValley]
	mov     cx,[cHandles]		; Loop through the handle table
SEISA_09a:
	cmp	[bx].Flags,FREEFLAG	; is this a valid free memory block?
	jnz	SEISA_09b		; branch if not
	cmp	[bx].Base.hi, 0
	jnz	SEISA_09b
	cmp	[bx].Base.lo,1024	; based at 1Meg?
	jz	SEISA_09c		; yup...

SEISA_09b:
	add	bx,SIZE Handle
	loop    SEISA_09a
	jmp	short SEISA_09e

SEISA_09c:
	cmp	fEISA, 0		; want all EISA memory, regardless?
	jz	SEISA_default		; no...

ifdef WIN30COMPATIBLE		;GetInt15Memory has an ifdef WIN30COMPATIBLE
.err				;  that would be silly to use with the
endif				;  following code

	call	GetInt15Memory		; yes, start EISA block above current
	add	[bx].Base.lo, ax	;   Int 15h/88h line.  The Int 15h mem
	adc	[bx].Base.hi, 0 	;   will be added when Int 15h hooked.
	sub	[bx].Len.lo, ax 	;   Existing hook and /INT15= code
	sbb	[bx].Len.hi, 0		;   will work as before.
	jc	SEISA_09d		; (just for safeties sake)
	mov	ax, [bx].Len.lo 	; Len will be 0 if Int 15h covers
	or	ax, [bx].Len.hi 	;   entire EISA block
	jz	SEISA_09d
	jmp	short SEISA_09e

SEISA_default:
	cmp	[bx].Len.hi, 0		; If the length is > 64 Meg (which is
	jz	SEISA_09d		;   the max that Int 15h/88h could
	inc	[bx].Base.hi		;   return), keep the memory above
	dec	[bx].Len.hi		;   that for XMS
	jmp	short SEISA_09e

SEISA_09d:
	mov	[bx].Flags,UNUSEDFLAG	; free the block at 1024

SEISA_09e:
	pop	es
	assume	es:nothing

SEISA_exit:
	mov	ss,save_ss
	mov	sp,save_sp		; restore normal stack
	ret
	assume	ds:nothing

ScanEISA	endp

;	The buffer for scanning EISA devices is big, but disposable

ZDS_Buffer	label	byte		; also use for Zenith memory check

EISABuffer	db	22h dup (0)
EISA_FncInfo	db	(73h-22h) dup (0)
EISA_MemConfig	db	(320-73h) dup (0)

		db	(512-320) dup (0)	; make it 512 for Zenith

	db	2000 dup (?)
EISA_Stack:

_text	ends

ifdef	debug_tsr			;-------------------------------

EndStmt equ	<end	ExeStart>

STACK	segment	stack 'STACK'
	db	1024 dup (?)
STACK	ends

else

EndStmt equ	<end>

endif					;-------------------------------

	EndStmt

⌨️ 快捷键说明

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