239 lines
5.5 KiB
PHP
239 lines
5.5 KiB
PHP
|
;++
|
||
|
;
|
||
|
; File Name:
|
||
|
;
|
||
|
; macro.inc
|
||
|
;
|
||
|
; Author:
|
||
|
;
|
||
|
; Thomas Parslow [tomp]
|
||
|
;
|
||
|
; Created:
|
||
|
;
|
||
|
; 27-Feb-91
|
||
|
;
|
||
|
; Abstract:
|
||
|
;
|
||
|
; The macros used for creating the exported entry points the
|
||
|
; OS loader will use for basic h/w dependent services. These
|
||
|
; services are:
|
||
|
;
|
||
|
; o Disk I/O
|
||
|
; o Character I/O
|
||
|
;
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
; EXPORT_ENTRY_MACRO
|
||
|
; We arrive here from the OS loader with a 32bit CS. That is, we're
|
||
|
; executing the code with cs:eip where cs contains a selector for a
|
||
|
; 32bit flat segment. We want to get to a 16bit cs. That is, cs:ip.
|
||
|
; The entry points are exported as 32bit near pointers to the OS loader.
|
||
|
; All code in the SU module is identity mapped so the flat 32bit offset
|
||
|
; is equal to the physical address.
|
||
|
;
|
||
|
; Therefore, we export the 32bit physical address as the
|
||
|
; entry point and the code may be executed with either the 32bit
|
||
|
; flat cs or the SU module's 16bit based cs. Before we can switch
|
||
|
; modes we must load all of the segment registers with selectors for
|
||
|
; 16bit segments. We start by pushing a far pointer to a label in
|
||
|
; the macro and then doing a retf. This allows us to fall through
|
||
|
; to the next instruction, but we're now executing through cs:ip
|
||
|
; with a 16bit CS.
|
||
|
;
|
||
|
; Output:
|
||
|
;
|
||
|
; (ebx) = pointer to stack frame (and top of 32bit stack).
|
||
|
;
|
||
|
|
||
|
EXPORT_ENTRY_MACRO macro entryname
|
||
|
LOCAL exp1
|
||
|
_TEXT32 segment para use32 public 'CODE'
|
||
|
ASSUME CS:_TEXT32
|
||
|
ALIGN 4
|
||
|
Public EntryName
|
||
|
EntryName LABEL near
|
||
|
;
|
||
|
; We've go a 32bit CS:EIP - go to a 16bit CS:IP
|
||
|
|
||
|
push dword ptr SuCodeSelector
|
||
|
push dword ptr (offset exp1)
|
||
|
|
||
|
retf
|
||
|
_TEXT32 ends
|
||
|
ASSUME CS:_TEXT
|
||
|
ALIGN 4
|
||
|
exp1:
|
||
|
;
|
||
|
; Save caller's EBP register and stack pointer (ESP)
|
||
|
;
|
||
|
|
||
|
push ebp
|
||
|
push ebx
|
||
|
push esi
|
||
|
push edi
|
||
|
mov ebx,esp
|
||
|
;
|
||
|
; Load all the segment registers with 16bit segment selectors
|
||
|
;
|
||
|
mov ax,SuDataSelector
|
||
|
mov ds,ax
|
||
|
mov ss,ax
|
||
|
;
|
||
|
; Set the stack to the top of the segment. We can do this now since
|
||
|
; all of the OS loader's code has already be relocated. Also, we need
|
||
|
; plenty of stack since we'll be calling BIOS routines.
|
||
|
;
|
||
|
mov esp,EXPORT_STACK
|
||
|
push ebx ; save the caller's esp
|
||
|
endm
|
||
|
;
|
||
|
; EXPORT_ENTRY_MACRO end
|
||
|
;
|
||
|
|
||
|
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
; Name:
|
||
|
;
|
||
|
; ExportExit
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
;
|
||
|
; Notes:
|
||
|
;
|
||
|
; EAX = return code and MUST be preserved by this macro.
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
EXPORT_EXIT_MACRO macro
|
||
|
;
|
||
|
; Next get caller's esp that we saved upon entry on the 16bit stack
|
||
|
;
|
||
|
pop ebx ; get caller's esp
|
||
|
;
|
||
|
; Restore flat selectors in segment registers.
|
||
|
;
|
||
|
mov dx,KeDataSelector
|
||
|
mov ds,dx
|
||
|
mov ss,dx
|
||
|
mov es,dx
|
||
|
mov esp,ebx
|
||
|
|
||
|
|
||
|
;
|
||
|
; Restore callers' ebp that we saved on the 32bit stack
|
||
|
;
|
||
|
pop edi
|
||
|
pop esi
|
||
|
pop ebx
|
||
|
pop ebp ; (ebp) = caller's ebp
|
||
|
|
||
|
;
|
||
|
; Pull callers flat return address off stack and push the
|
||
|
; flat code selector followed by the return offset, then
|
||
|
; execute a far return and we'll be back in the OS loaders code space.
|
||
|
;
|
||
|
pop edx ; (edx) = caller's return address
|
||
|
push dword ptr KeCodeSelector
|
||
|
push edx
|
||
|
db OVERRIDE
|
||
|
retf
|
||
|
endm
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
;
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
RE_ENABLE_PAGING_MACRO macro
|
||
|
extrn _EnableProtectPaging:near
|
||
|
push RE_ENABLING
|
||
|
call _EnableProtectPaging
|
||
|
add sp,2
|
||
|
endm
|
||
|
|
||
|
ENTER_REALMODE_MACRO macro
|
||
|
extrn _RealMode:near
|
||
|
call _RealMode
|
||
|
endm
|
||
|
|
||
|
|
||
|
|
||
|
WAIT_FOREVER_MACRO macro
|
||
|
LOCAL wf1
|
||
|
wf1: jmp wf1
|
||
|
endm
|
||
|
|
||
|
;++
|
||
|
;
|
||
|
; MAKE_STACK_FRAME_MACRO
|
||
|
;
|
||
|
; Arguments:
|
||
|
;
|
||
|
; _FrameName_ - is the name of the structure defining the
|
||
|
; stack frame layout.
|
||
|
;
|
||
|
; _PointerRegister_ - is the register containing the linear pointer to
|
||
|
; the top of the stack frame.
|
||
|
; ProtectMode ONLY
|
||
|
;
|
||
|
;--
|
||
|
|
||
|
MAKE_STACK_FRAME_MACRO macro _FrameName_ , _PointerRegister_
|
||
|
Local msf1
|
||
|
mov ecx, (size _FrameName_)/2
|
||
|
mov esi,_PointerRegister_ ; (esi) = offset of argument frame
|
||
|
add esi,20 ; account for ebp, ebx, esi, edi and
|
||
|
; return address
|
||
|
push KeDataSelector ; (ax) = Flat 32bit segment selector
|
||
|
pop ds ; (ds:esi) points to argument frame
|
||
|
push ss ;
|
||
|
pop es ; (es) = 16bit stack selector
|
||
|
sub sp, size _FrameName_ ; make room for the arguments
|
||
|
xor edi,edi ; clear out upper 16bits of edi
|
||
|
mov di,sp ; (es:edi) points to top of stack
|
||
|
msf1:
|
||
|
mov ax,[esi]
|
||
|
mov es:[edi],ax
|
||
|
add esi,2
|
||
|
add edi,2
|
||
|
loop msf1
|
||
|
push es ;
|
||
|
pop ds ; put 16bit selector back into ds
|
||
|
endm
|
||
|
|
||
|
|
||
|
REMOVE_STACK_FRAME_MACRO macro _FrameName_
|
||
|
|
||
|
add sp, size _FrameName_
|
||
|
endm
|
||
|
|
||
|
|
||
|
;BuildDescriptor macro Base,Limit,Access,Dpl,Stype
|
||
|
; dw (Limit AND 0ffffh)
|
||
|
; dw (Base AND 0ffffh)
|
||
|
; db ((Base SHR 16) AND 0ffh)
|
||
|
; db (Gran + Dpl + Stype)
|
||
|
; db ((Limit SHR 16) AND 0ffh)
|
||
|
; db ((Base SHR 24) AND 0ffh)
|
||
|
; endm
|
||
|
|
||
|
|
||
|
|
||
|
;
|
||
|
;
|
||
|
;
|
||
|
RETURNCODE_IN_EAX_MACRO macro
|
||
|
|
||
|
shl edx,16
|
||
|
mov dx,ax
|
||
|
mov eax,edx
|
||
|
endm
|