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