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