📄 _pm.asm
字号:
ifndef flatmodel
_PM_savedDS dw _DATA ; Saved value of DS
endif
;----------------------------------------------------------------------------
; void PM_saveDS(void)
;----------------------------------------------------------------------------
; Save the value of DS into a section of the code segment, so that we can
; quickly load this value at a later date in the PM_loadDS() routine from
; inside interrupt handlers etc. The method to do this is different
; depending on the DOS extender being used.
;----------------------------------------------------------------------------
cprocstartdll16 PM_saveDS
ifdef flatmodel
mov [_PM_savedDS],ds ; Store away in data segment
endif
ret
cprocend
;----------------------------------------------------------------------------
; void PM_loadDS(void)
;----------------------------------------------------------------------------
; Routine to load the DS register with the default value for the current
; DOS extender. Only the DS register is loaded, not the ES register, so
; if you wish to call C code, you will need to also load the ES register
; in 32 bit protected mode.
;----------------------------------------------------------------------------
cprocstartdll16 PM_loadDS
mov ds,[cs:_PM_savedDS] ; We can access the proper DS through CS
ret
cprocend
ifdef flatmodel
;----------------------------------------------------------------------------
; ibool DPMI_allocateCallback(void (*pmcode)(), void *rmregs, long *RMCB)
;----------------------------------------------------------------------------
cprocstart _DPMI_allocateCallback
ARG pmcode:CPTR, rmregs:DPTR, RMCB:DPTR
enter_c
push ds
push es
push cs
pop ds
mov esi,[pmcode] ; DS:ESI -> protected mode code to call
mov edi,[rmregs] ; ES:EDI -> real mode register buffer
mov ax,303h ; AX := allocate realmode callback function
int 31h
mov eax,0 ; Return failure!
jc @@Fail
mov eax,[RMCB]
shl ecx,16
mov cx,dx
mov [es:eax],ecx ; Return real mode address
mov eax,1 ; Return success!
@@Fail: pop es
pop ds
leave_c
ret
cprocend
;----------------------------------------------------------------------------
; void DPMI_freeCallback(long RMCB)
;----------------------------------------------------------------------------
cprocstart _DPMI_freeCallback
ARG RMCB:ULONG
enter_c
mov cx,[WORD RMCB+2]
mov dx,[WORD RMCB] ; CX:DX := real mode callback
mov ax,304h
int 31h
leave_c
ret
cprocend
endif
; Macro to delay briefly to ensure that enough time has elapsed between
; successive I/O accesses so that the device being accessed can respond
; to both accesses even on a very fast PC.
ifdef USE_NASM
%macro DELAY 0
jmp short $+2
jmp short $+2
jmp short $+2
%endmacro
%macro IODELAYN 1
%rep %1
DELAY
%endrep
%endmacro
else
macro DELAY
jmp short $+2
jmp short $+2
jmp short $+2
endm
macro IODELAYN N
rept N
DELAY
endm
endm
endif
;----------------------------------------------------------------------------
; uchar _PM_readCMOS(int index)
;----------------------------------------------------------------------------
; Read the value of a specific CMOS register. We do this with both
; normal interrupts and NMI disabled.
;----------------------------------------------------------------------------
cprocstart _PM_readCMOS
ARG index:UINT
push _bp
mov _bp,_sp
pushfd
mov al,[BYTE index]
or al,80h ; Add disable NMI flag
cli
out 70h,al
IODELAYN 5
in al,71h
mov ah,al
xor al,al
IODELAYN 5
out 70h,al ; Re-enable NMI
sti
mov al,ah ; Return value in AL
popfd
pop _bp
ret
cprocend
;----------------------------------------------------------------------------
; void _PM_writeCMOS(int index,uchar value)
;----------------------------------------------------------------------------
; Read the value of a specific CMOS register. We do this with both
; normal interrupts and NMI disabled.
;----------------------------------------------------------------------------
cprocstart _PM_writeCMOS
ARG index:UINT, value:UCHAR
push _bp
mov _bp,_sp
pushfd
mov al,[BYTE index]
or al,80h ; Add disable NMI flag
cli
out 70h,al
IODELAYN 5
mov al,[value]
out 71h,al
xor al,al
IODELAYN 5
out 70h,al ; Re-enable NMI
sti
popfd
pop _bp
ret
cprocend
ifdef flatmodel
;----------------------------------------------------------------------------
; int _PM_pagingEnabled(void)
;----------------------------------------------------------------------------
; Returns 1 if paging is enabled, 0 if not or -1 if not at ring 0
;----------------------------------------------------------------------------
cprocstart _PM_pagingEnabled
mov eax,-1
ifdef DOS4GW
mov cx,cs
and ecx,3
jz @@Ring0
cmp [UINT _PM_haveCauseWay],0
jnz @@Ring0
jmp @@Exit
@@Ring0:
mov eax,cr0 ; Load CR0
shr eax,31 ; Isolate paging enabled bit
endif
@@Exit: ret
cprocend
;----------------------------------------------------------------------------
; _PM_getPDB - Return the Page Table Directory Base address
;----------------------------------------------------------------------------
cprocstart _PM_getPDB
ifdef DOS4GW
mov ax,cs
and eax,3
jz @@Ring0
cmp [UINT _PM_haveCauseWay],0
jnz @@Ring0
endif
; Call VxD if running at ring 3 in a DOS box
cmp [WORD _PM_VXD_sel],0
jz @@Fail
mov eax,PMHELP_GETPDB
ifdef USE_NASM
call far dword [_PM_VXD_off]
else
call [FCPTR _PM_VXD_off]
endif
ret
@@Ring0:
ifdef DOS4GW
mov eax,cr3
and eax,0FFFFF000h
ret
endif
@@Fail: xor eax,eax
ret
cprocend
;----------------------------------------------------------------------------
; PM_flushTLB - Flush the Translation Lookaside buffer
;----------------------------------------------------------------------------
cprocstart PM_flushTLB
mov ax,cs
and eax,3
jz @@Ring0
ifdef DOS4GW
cmp [UINT _PM_haveCauseWay],0
jnz @@Ring0
endif
; Call VxD if running at ring 3 in a DOS box
cmp [WORD _PM_VXD_sel],0
jz @@Fail
mov eax,PMHELP_FLUSHTLB
ifdef USE_NASM
call far dword [_PM_VXD_off]
else
call [FCPTR _PM_VXD_off]
endif
ret
@@Ring0:
ifdef DOS4GW
wbinvd ; Flush the CPU cache
mov eax,cr3
mov cr3,eax ; Flush the TLB
endif
@@Fail: ret
cprocend
endif
;----------------------------------------------------------------------------
; void _PM_VxDCall(VXD_regs far *r,uint off,uint sel);
;----------------------------------------------------------------------------
cprocstart _PM_VxDCall
ARG r:DPTR, off:UINT, sel:UINT
enter_c
; Load all registers from the registers structure
mov ebx,[r]
mov eax,[ebx+0]
mov ecx,[ebx+8]
mov edx,[ebx+12]
mov esi,[ebx+16]
mov edi,[ebx+20]
mov ebx,[ebx+4] ; Trashes BX structure pointer!
; Call the VxD entry point (on stack)
ifdef USE_NASM
call far dword [off]
else
call [FCPTR off]
endif
; Save all registers back in the structure
push ebx ; Push EBX onto stack for later
mov ebx,[r]
mov [ebx+0],eax
mov [ebx+8],ecx
mov [ebx+12],edx
mov [ebx+16],esi
mov [ebx+20],edi
pop [DWORD ebx+4] ; Save value of EBX from stack
leave_c
ret
cprocend
endcodeseg _pmdos
END ; End of module
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -