📄 _pm.asm
字号:
;****************************************************************************;*;* SciTech OS Portability Manager Library;*;* ========================================================================;*;* The contents of this file are subject to the SciTech MGL Public;* License Version 1.0 (the "License"); you may not use this file;* except in compliance with the License. You may obtain a copy of;* the License at http://www.scitechsoft.com/mgl-license.txt;*;* Software distributed under the License is distributed on an;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or;* implied. See the License for the specific language governing;* rights and limitations under the License.;*;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.;*;* The Initial Developer of the Original Code is SciTech Software, Inc.;* All Rights Reserved.;*;* ========================================================================;*;* Language: 80386 Assembler, TASM 4.0 or NASM;* Environment: IBM PC Real mode and 16/32 bit protected mode;*;* Description: Low level assembly support for the PM library specific to;* MSDOS.;*;**************************************************************************** IDEALinclude "scitech.mac" ; Memory model macrosheader _pmdos ; Set up memory modelbegdataseg _pmdosifndef flatmodelstruc rmregs_sax dw ?ax_high dw ?bx dw ?bx_high dw ?cx dw ?cx_high dw ?dx dw ?dx_high dw ?si dw ?si_high dw ?di dw ?di_high dw ?cflag dw ?cflag_high dw ?ends rmregs_sRMREGS = (rmregs_s PTR es:bx)struc rmsregs_ses dw ?cs dw ?ss dw ?ds dw ?ends rmsregs_sRMSREGS = (rmsregs_s PTR es:bx)endif ; !flatmodelifdef flatmodel cextern _PM_savedDS,USHORT cextern _PM_VXD_off,UINT cextern _PM_VXD_sel,UINTifdef DOS4GW cextern _PM_haveCauseWay,UINTendifendifintel_id db "GenuineIntel" ; Intel vendor IDPMHELP_GETPDB EQU 0026hPMHELP_FLUSHTLB EQU 0027henddataseg _pmdosP586begcodeseg _pmdos ; Start of code segmentifndef flatmodel;----------------------------------------------------------------------------; void PM_callRealMode(unsigned s,unsigned o, RMREGS *regs,; RMSREGS *sregs);----------------------------------------------------------------------------; Calls a real mode procedure, loading the appropriate registers values; from the passed in structures. Only the DS and ES register are loaded; from the SREGS structure.;----------------------------------------------------------------------------cprocstart PM_callRealMode ARG s:WORD, o:WORD, regs:DWORD, sregs:DWORD LOCAL addr:DWORD, bxVal:WORD, esVal:WORD, flags:WORD = LocalSize enter_c push ds push es mov ax,[o] ; Build the address to call in 'addr' mov [WORD addr],ax mov ax,[s] mov [WORD addr+2],ax les bx,[sregs] mov ax,[RMSREGS.ds] mov ds,ax ; DS := passed in value mov ax,[RMSREGS.es] mov [esVal],ax les bx,[regs] mov ax,[RMREGS.bx] mov [bxVal],ax mov ax,[RMREGS.ax] ; AX := passed in value mov cx,[RMREGS.cx] ; CX := passed in value mov dx,[RMREGS.dx] ; DX := passed in value mov si,[RMREGS.si] ; SI := passed in value mov di,[RMREGS.di] ; DI := passed in value push bp push [esVal] pop es ; ES := passed in value mov bx,[bxVal] ; BX := passed in value call [addr] ; Call the specified routine pushf ; Save flags for later pop [flags] pop bp push es pop [esVal] push bx pop [bxVal] les bx,[sregs] push ds pop [RMSREGS.ds] ; Save value of DS push [esVal] pop [RMSREGS.es] ; Save value of ES les bx,[regs] mov [RMREGS.ax],ax ; Save value of AX mov [RMREGS.cx],cx ; Save value of CX mov [RMREGS.dx],dx ; Save value of DX mov [RMREGS.si],si ; Save value of SI mov [RMREGS.di],di ; Save value of DI mov ax,[flags] ; Return flags and ax,1h ; Isolate carry flag mov [RMREGS.cflag],ax ; Save carry flag status mov ax,[bxVal] mov [RMREGS.bx],ax ; Save value of BX pop es pop ds leave_c retcprocendendif;----------------------------------------------------------------------------; void PM_segread(PMSREGS *sregs);----------------------------------------------------------------------------; Read the current value of all segment registers;----------------------------------------------------------------------------cprocstartdll16 PM_segread ARG sregs:DPTR enter_c mov ax,es _les _si,[sregs] mov [_ES _si],ax mov [_ES _si+2],cs mov [_ES _si+4],ss mov [_ES _si+6],ds mov [_ES _si+8],fs mov [_ES _si+10],gs leave_c retcprocend; Create a table of the 256 different interrupt calls that we can jump; intoifdef USE_NASM%assign intno 0intTable:%rep 256 db 0CDh db intno%assign intno intno + 1 ret nop%endrepelseintno = 0intTable: REPT 256 db 0CDh db intnointno = intno + 1 ret nop ENDMendif;----------------------------------------------------------------------------; _PM_genInt - Generate the appropriate interrupt;----------------------------------------------------------------------------cprocnear _PM_genInt push _ax ; Save _ax push _bx ; Save _bxifdef flatmodel mov ebx,[UINT esp+12] ; EBX := interrupt numberelse mov bx,sp ; Make sure ESP is zeroed mov bx,[UINT ss:bx+6] ; BX := interrupt numberendif mov _ax,offset intTable ; Point to interrupt generation table shl _bx,2 ; _BX := index into table add _ax,_bx ; _AX := pointer to interrupt codeifdef flatmodel xchg eax,[esp+4] ; Restore eax, and set for intelse mov bx,sp xchg ax,[ss:bx+2] ; Restore ax, and set for intendif pop _bx ; restore _bx retcprocend;----------------------------------------------------------------------------; int PM_int386x(int intno, PMREGS *in, PMREGS *out,PMSREGS *sregs);----------------------------------------------------------------------------; Issues a software interrupt in protected mode. This routine has been; written to allow user programs to load CS and DS with different values; other than the default.;----------------------------------------------------------------------------cprocstartdll16 PM_int386x ARG intno:UINT, inptr:DPTR, outptr:DPTR, sregs:DPTR LOCAL flags:UINT, sv_ds:UINT, sv_esi:ULONG = LocalSize enter_c push ds push es ; Save segment registers push fs push gs _lds _si,[sregs] ; DS:_SI -> Load segment registers mov es,[_si] mov bx,[_si+6] mov [sv_ds],_bx ; Save value of user DS on stack mov fs,[_si+8] mov gs,[_si+10] _lds _si,[inptr] ; Load CPU registers mov eax,[_si] mov ebx,[_si+4] mov ecx,[_si+8] mov edx,[_si+12] mov edi,[_si+20] mov esi,[_si+16] push ds ; Save value of DS push _bp ; Some interrupts trash this! clc ; Generate the interrupt push [UINT intno] mov ds,[WORD sv_ds] ; Set value of user's DS selector call _PM_genInt pop _bp ; Pop intno from stack (flags unchanged) pop _bp ; Restore value of stack frame pointer pop ds ; Restore value of DS pushf ; Save flags for later pop [UINT flags] push esi ; Save ESI for later pop [DWORD sv_esi] push ds ; Save DS for later pop [UINT sv_ds] _lds _si,[outptr] ; Save CPU registers mov [_si],eax mov [_si+4],ebx mov [_si+8],ecx mov [_si+12],edx push [DWORD sv_esi] pop [DWORD _si+16] mov [_si+20],edi mov _bx,[flags] ; Return flags and ebx,1h ; Isolate carry flag mov [_si+24],ebx ; Save carry flag status _lds _si,[sregs] ; Save segment registers mov [_si],es mov _bx,[sv_ds] mov [_si+6],bx ; Get returned DS from stack mov [_si+8],fs mov [_si+10],gs pop gs ; Restore segment registers pop fs pop es pop ds leave_c retcprocend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -