himem2.asm

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

ASM
2,333
字号
	jnz	no_ZBim			; done if not Zenith machine

;	Now we've got to go out and look for 256KBytes at 0fa0000h
;	  Let's use the BlockMove function to help us with that so we
;	  don't have to write any messy protect mode code.  We'll
;	  snag a handle and set up a dummy block while we work.

	cli
	push	es
	mov	es,hiseg
	assume	es:funky
	mov	di,[KiddValley]
	mov	cx,[cHandles]

chk_zb0:
	cmp	[di].Flags,UNUSEDFLAG
	jz	ZBim_01			; brif found free handle
	add	di,SIZE Handle
	loop	chk_zb0
	pop	es
	sti				; restore interrupts
no_ZBim:
	ret

ZBim_01:
	mov	[di].cLock,1		; lock it
	mov	[di].Base.lo,3e80h	; number of K at 0fa0000h
	mov	[di].Base.hi,0
	mov	[di].Len.lo,256
	mov	[di].Len.hi, 0
	mov	[di].Flags, USEDFLAG
	pop	es
	assume	es:nothing
	sti

	mov	save_ss,ss		; get more elbow room for this
	mov	save_sp,sp
	push	cs
	pop	ss
	mov	sp,offset EISA_stack

;	allocate a move structure on the stack
;	  for now, we'll just test the first 512 bytes.  It might be
;	  a good idea to test the whole damn thing, but a lot more work.

	sub	sp,0fffeh and (1+SIZE MoveExtendedStruc)
	push    ss			; point es:si to stack frame
	pop	es
	mov	si,sp

	mov	es:[si].SourceHandle,0	; move from conventional memory
	mov	es:[si].DestHandle,di	; to our fake block at 0fa0000h
	mov	es:word ptr [si].DestOffset,0 ; move data to base of block
	mov	es:word ptr [si].DestOffset+2,0

	mov	es:word ptr [si].SourceOffset,8000h
	mov	es:word ptr [si].SourceOffset+2,0f000h	; move from ROM
	mov	es:word ptr [si].bCount,512	; move 512 bytes
	mov	es:word ptr [si].bCount+2,0

	push	si			; save move structure
	push    di			; save handle

	push	cs			; fake far call
	call	BlockMove

	pop	di
	pop	si

;	now move the 512 bytes back out into our buffer and compare

	push	ss
	pop	es
	mov	es:[si].SourceHandle,di	; move from the fake block
	mov	es:[si].DestHandle,0	; to conventional memory
	mov	es:word ptr [si].DestOffset,offset ZDS_Buffer
	mov	es:word ptr [si].DestOffset+2,cs
	mov	es:word ptr [si].SourceOffset,0
	mov	es:word ptr [si].SourceOffset+2,0

	push	di			; save handle for deallocation

	push	cs			; fake far call
	call	BlockMove


;	now all we've gotta do is see if the ZDS_Buffer matches the
;	  first 512 bytes of the ROM at 0f000:8000

	mov	es,f000
	mov	di,8000h
	mov	si,offset ZDS_Buffer
	mov	cx,256			; 256 words
	repz	cmpsw			; does it match?
	jnz	check_zb1		; done if not

;	Use AddMem to add the memory to our pool, even though we
;	  could have just marked the fake block we allocated as UNUSED.
;	  Why?  What if some other source (like and EISA BIOS) also
;	  told us about that same memory?  We might as well take advantage
;	  of all of the smarts in AddMem to eliminate overlaps.

	mov	cx,3e80h		; add memory to pool then
	mov	ax,256
	xor	dx, dx
	mov	bx, dx

	mov	di, pAddMem
	push	cs
	call	call_hi_in_di

;	Now we've got to fill the damn block, cuz the
;	  parity isn't initialized yet.

	push	ds
	pop	es
	mov	di,offset ZDS_Buffer
	mov	cx,256
	xor	ax,ax
	rep	stosw			; fill 512 byte block with zeros

	push	ss			; point es: to stack frame again
	pop	es
	mov	es:[si].SourceHandle,0	; move from conventional memory
	pop	di
	push	di			; get handle from stack
	mov	es:[si].DestHandle,di	; to our fake block at 0fa0000h
	mov	es:word ptr [si].DestOffset,0 ; move data to base of block
	mov	es:word ptr [si].DestOffset+2,0

	mov	es:word ptr [si].SourceOffset,offset ZDS_Buffer
	mov	es:word ptr [si].SourceOffset+2,cs	; move from ZDS_Buffer
	mov	es:word ptr [si].bCount,512	; move 512 bytes
	mov	es:word ptr [si].bCount+2,0
	mov	cx,512			; 256K/512 bytes
zfill_loop:
	push	es
	push	si
	push	cx

	push	cs			; fake far call
	call	BlockMove

	pop	cx
	pop	si
	pop	es
	add	es:word ptr [si].DestOffset,512
	jnc	zfill_skip
	inc	es:word ptr [si].DestOffset+2
zfill_skip:
	loop	zfill_loop

check_zb1:

;	Release the move structure stack frame

	pop	di			; restore temporary handle
	add	sp,0fffeh and (1+SIZE MoveExtendedStruc)
	push	es
	mov	es,hiseg
	assume	es:funky
	mov	[di].Flags,UNUSEDFLAG	; then handle is free again
	pop	es
	assume	es:nothing

	mov	ss,save_ss
	mov	sp,save_sp		; restore normal stack

	ret

CheckZBim	endp

;	Call MoveIt function in other segment.  Make sure we enable A20.

BlockMove	proc	near

ifdef debug_tsr
        jmp     MoveIt
else
	mov	di,MoveIt		; get function in funky segment
	jmp	call_hi_in_di
endif

BlockMove	endp

;*----------------------------------------------------------------------*
;*									*
;*  GetInt15Memory -							*
;*									*
;*	Returns the amount of memory INT 15h, Function 88h says is free	*
;*									*
;*  ARGS:   None							*
;*  RETS:   AX = Amount of free extended memory in K-bytes		*
;*  REGS:   AX and Flags are clobbered					*
;*									*
;*----------------------------------------------------------------------*


GetInt15Memory proc near

	mov	ah,88h			; snag the int 15h memory
	clc
	int	15h			; Is Function 88h around?
	jnc     xret_geti15
	xor	ax,ax			; No, return 0
xret_geti15:

ifdef WIN30COMPATIBLE
	cmp	ax,15*1024		; Limit himem.sys to using 15 meg
	jb	@f			;   of extended memory for apps
	mov	ax,15*1024		;   that don't deal with > 24 bit
@@:					;   addresses
endif
	ret

GetInt15Memory endp

;*--------------------------------------------------------------------------*
;*                                                                          *
;*  GetBIGMemory -                                                          *
;*                                                                          *
;*      Returns the amount of memory Extended INT 15h, >16 Meg              *
;*      Uses new INT 15 function E801                                       *
;*                                                                          *
;*  ARGS:   None                                                            *
;*  RETS:   None							    *
;*  REGS:   AX and Flags are clobbered                                      *
;*                                                                          *
;*--------------------------------------------------------------------------*

GetBIGMemory proc near

        push    dx
        push    cx
        push    bx
        push    si
        push    es

        call    IsEISAMachine       ; Is this an EISA machine ?
	jc	short GBM_end	    ;  Y: Ignore parameter

	call	Compaq386	    ; is it a Compaq system?
	jnz	short GBM_end

        mov     ax,0E801h           ; determine >16M memory
        clc
	int	15h		    ; Is Function 88h around?
	jc	short GBM_end	    ; No, exit

        mov     ax,bx               ; DX:AX to = length of block in 1K blocks
        mov     dx,64               ; DX should always be zero (16M extra max)
        mul     dx

        mov     cx,BIGISA_START     ; BIGISA_START=16384 in (HIMEM.INC)
	xor	dx, dx
	mov	bx, dx

	mov	di, pAddMem
	push	cs
	call	call_hi_in_di	    ; add that memory to our tables

        les     si,dword ptr pInt15Vector   ; Save the current INT 15 vector.

	cli
        mov     ax,offset ISA15Handler      ; Exchange the old vector with
        xchg    ax,es:[si][0]               ;  the new one.
        mov     word ptr [PrevISAInt15][0],ax
        mov     ax,cs
        xchg    ax,es:[si][2]
	mov	word ptr [PrevISAInt15][2],ax
	sti

GBM_end:
        pop     es
        pop     si
        pop     bx
        pop     cx
        pop     dx
        ret

GetBIGMemory endp

;*--------------------------------------------------------------------------*
;*                                                                          *
;*  IsEISAMachine                                           HARDWARE DEP.   *
;*                                                                          *
;*  Determine if we are on an EISA machine                                  *
;*                                                                          *
;*  ARGS:   None                                                            *
;*  RETS:   CY = 1 if we're on a EISA machine                               *
;*             = 0 otherwise                                                *
;*  REGS:   Flags clobbered                                                 *
;*                                                                          *
;*--------------------------------------------------------------------------*

pEISASTRUC  equ     0FFD9h      ; offset to EISA name in ROM
pROM	    equ     0F000h	; ROM segment

IsEISAMachine     proc    near                                            ;

        push    es                      ; save registers we'll use
        push    bx                      ;  ...

    ;-----------------------------------------
    ; Determine if this is an EISA system by
    ;  looking for ROM signature
    ;-----------------------------------------
        mov     bx,pROM
        mov     es,bx                   ; ROM segment
        mov     bx,pEISASTRUC           ; offset to EISA name
        cmp     word ptr es:[bx],'IE'   ; Q: is this an 'EISA' system
        jne     short IEM_NO            ;  N: set flag and return
        cmp     word ptr es:[bx+2],'AS' ;
        je      short IEM_YES           ;  Y: set flag and return

IEM_NO:
        clc                             ; Not an EISA machine...
        jmp     short IEM_Done

IEM_YES:
        stc                             ; Yes, it is an EISA box
IEM_Done:
        pop     bx
        pop     es

        ret

IsEISAMachine        endp

;*----------------------------------------------------------------------*
;*									*
;*  GetParms -								*
;*									*
;*	Get any parameters off of the HIMEM command line		*
;*									*
;*  ARGS:   None							*
;*  RETS:   None							*
;*  REGS:   AX, BX, CX, DX, DI, SI, ES and Flags clobbered		*
;*									*
;*  Side Effects:   cHandles and MinHMASize may be changed		*
;*									*
;*----------------------------------------------------------------------*

GPArgPtr	dd	?
GPRegSave	dw	?

	public	GetParms

GetParms    proc    near

	cld				; better safe than sorry

	push	ds

ifdef	debug_tsr			;-------------------------------
	lds	si,lpCmdLine
else					;-------------------------------
	les	di,[pReqHdr]		; Running as a device driver
	lds	si,es:[di].pCmdLine	; DS:SI points to first char
					;   after "DEVICE="
@@:	call	GPGetChar		; Skip over driver name, up to
	jc	GPDatsAll		;   first blank or / or eol
	jz	GPNextArg
	cmp	al,'/'
	jnz	@b
	dec	si			; Backup to get / again
endif					;-------------------------------

	assume	ds:nothing,es:nothing

;	Scan until we see a non-blank or the end of line.

GPNextArg:
	call	GPGetChar
	jc	GPDatsAll		; eol
	jz	GPNextArg		; blank

	mov	word ptr cs:[GPArgPtr], si	; save ptr to start of arg
	mov	word ptr cs:[GPArgPtr+2], ds	;   incase we want to complain
	dec	word ptr cs:[GPArgPtr]		;   (GPGetChar points at next)

	cmp	al,'/'			; better be a / or not a valid arg
	jz	GPGotOne

;	Detected invalid parameter or value, complain to user

GPBadParm:
	mov	ah,9			; tell'm something isn't right
	push	cs
	pop	ds
	mov	dx, offset BadArgMsg
	call	DispErrMsg

	lds	si,cs:[GPArgPtr]	; backup to last parameter

GPBadDisp:
	call	GPGetChar		; disp arg up to space or eol
	jc	GPDatsAll		;  skips over bad arg while we're at it
	jz	GPNextArg

	cmp	al,'/'				; start of next arg?
	jnz	@f
	dec	si				; maybe yes, maybe no--might
	cmp	si,word ptr cs:[GPArgPtr]	;   be same arg
	jnz	GPNextArg			;   next, go process new arg
	inc	si				;   same, keep displaying
@@:
	mov	dl,al
	call	DispInfoChar
	jmp	short GPBadDisp

;	Finished, we're outta here...

GPDatsAll:
	jmp	GPExit

;	Save what we found and try to process as parameter without argument

GPGotOne:
	lodsb
	mov	cs:[GPRegSave],ax

	mov	bx, offset ParmTbl1	; Process parameters with no arguments
	call	GPCheckParm
	jc	GPNeedParm		; CY means it wasn't processed

GPSkip2Next:				; Parameter was processed, skip
	call	GPGetChar		;   over any remaining text in the
	jc	GPDatsAll		;   parameter name
	jz	GPNextArg
	cmp	al,'/'
	jnz	GPSkip2Next
	dec	si			; backup to get / again
	jmp	GPNextArg

;	Must need an argument -- scan for a number, EOL, or a space.

GPNeedParm:
	call	GPGetChar
	jc	GPBadParm
	jz	GPBadParm	; blank
	cmp	al,':'		; start of string arg
	je	GPString
	cmp	al,'='
	jne	GPNeedParm

;	Read the number at DS:SI into DX

GPNeedNum:
	call	GPGetChar
	jc	GPDatsAll
	cmp	al,'0'
	jb	GPNeedNum
	cmp	al,'9'
	ja	GPNeedNum

	xor	dx,dx
GPNumLoop:
	sub	al,'0'
	cbw
	add	dx,ax
	call	GPGetChar
	jc	GPNumDone
	jz	GPNumDone
	cmp	al,'0'
	jb	GPBadParm
	cmp	al,'9'
	ja	GPBadParm
	shl	dx,1		; Stupid multiply DX by 10
	mov	bx,dx
	shl	dx,1
	shl	dx,1
	add	dx,bx
	jmp	short GPNumLoop

;	Move the string arg from ds:si to StringParm

GPString:
	mov	cx,(SIZE StringParm) - 1
	push	cs
	pop	es
	mov	di,offset _text:StringParm

GPStrLoop:
	call	GPGetChar
	jc	GPStrDone
	jz	GPStrDone
	stosb
	loop	GPStrLoop

GPStrDone:

	mov	byte ptr es:[di],0	; Null terminate the string
	mov	dx,-1			; In case parm expects a num, give'm
					;   a likely invalid one

;	Which parameter are we dealing with here?

GPNumDone:
	xchg	ax,cs:[GPRegSave]

	mov	bx, offset ParmTbl2	; parameters with arguments
	call	GPCheckParm		; process it valid
	jnc	GPNextParm
	jmp	GPBadParm

GPNextParm:
	mov	ax,cs:[GPRegSave]	; are we at the end of the line?
	cmp	al,13			; may not be needed any longer...
	je	GPExit
	cmp	al,10
	je	GPExit
	jmp	GPNextArg

GPExit:
	call	GPPrintInfo		; Display user messages
	pop	ds
	ret

GetParms    endp


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

; In:  AL =  1st character of parameter
;      BX -> Parameter table to use
; Out: CY set if parameter not matched
;      CY clear if parameter matched, and routine will be called

GPCheckParm	proc	near

GPCP_loop:
	cmp	cs:[bx].cParmChar, 0	; end of table?
	je	GPCP_failed

	cmp	cs:[bx].cParmChar, al	; match?
	je	GPCP_match

	add	bx, SIZE ParmEntry
	jmp	short GPCP_loop

GPCP_match:
	clc				; got it, call routine to process
	call	cs:[bx].pParmRtn	; (handler returns with CY clr or set)
	ret

GPCP_failed:
	stc				; no match
	ret

GPCheckParm	endp


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

; Routines to process specific command line parameters

GPDoParameters	proc	near


;---------------------------------------

GPGotEISA:				; /EISA
	mov	fEISA, 0FFh
	ret				; (CY already clear)

GPGotVerbose:				; /VERBOSE
	mov	fQuiet, 0
	ret				; (CY already clear)

GPGotBigMem:				; /NOABOVE16
	cmp	byte ptr [si], 'O'	; /NOABOVE16 & /NUMHANDLES= both start
	jne	GPBadParmRet		;   with 'N', make sure only /NOABOVE16
					;   is processed here.
	mov	fBigMem, 0
	ret				; (CY already clear)

;	The /Z switch is for compatibility with pervious version of himem.
;	By default, himem will now call it's own XMMControl entry point to
;	enable/disable A20 around calls to himem code in the HMA.  The
;	external calls allow XMS hookers (like EMM386) to see the A20
;	changes.  The previous behavior of calling internal A20 routines
;	can be selected with the /Z switch in case the external (recursive)
;	calls cause compatibility problems with other software.

⌨️ 快捷键说明

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