📄 _pm.asm
字号:
ifndef flatmodel_PM_savedDS dw _DATA ; Saved value of DSendif;----------------------------------------------------------------------------; 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_saveDSifdef flatmodel mov [_PM_savedDS],ds ; Store away in data segmentendif retcprocend;----------------------------------------------------------------------------; 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 retcprocendifdef 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 retcprocend;----------------------------------------------------------------------------; 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 retcprocendendif; 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%endmacroelsemacro DELAY jmp short $+2 jmp short $+2 jmp short $+2endmmacro IODELAYN N rept N DELAY endmendmendif;----------------------------------------------------------------------------; 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 retcprocend;----------------------------------------------------------------------------; 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 retcprocendifdef 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,-1ifdef 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 bitendif@@Exit: retcprocend;----------------------------------------------------------------------------; _PM_getPDB - Return the Page Table Directory Base address;----------------------------------------------------------------------------cprocstart _PM_getPDBifdef DOS4GW mov ax,cs and eax,3 jz @@Ring0 cmp [UINT _PM_haveCauseWay],0 jnz @@Ring0endif; Call VxD if running at ring 3 in a DOS box cmp [WORD _PM_VXD_sel],0 jz @@Fail mov eax,PMHELP_GETPDBifdef 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 retendif@@Fail: xor eax,eax retcprocend;----------------------------------------------------------------------------; PM_flushTLB - Flush the Translation Lookaside buffer;----------------------------------------------------------------------------cprocstart PM_flushTLB mov ax,cs and eax,3 jz @@Ring0ifdef DOS4GW cmp [UINT _PM_haveCauseWay],0 jnz @@Ring0endif; Call VxD if running at ring 3 in a DOS box cmp [WORD _PM_VXD_sel],0 jz @@Fail mov eax,PMHELP_FLUSHTLBifdef 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 TLBendif@@Fail: retcprocendendif;----------------------------------------------------------------------------; 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 retcprocendendcodeseg _pmdos END ; End of module
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -