segfix.asm
来自「Dos6.0」· 汇编 代码 · 共 265 行
ASM
265 行
.386p
;******************************************************************************
title SEGFIX
;******************************************************************************
;
; (C) Copyright MICROSOFT Corp. 1989-1991
; (C) Copyright COMPAQ Computer Corp. 1989-1991
;
; Title: EMM386.EXE - MICROSOFT Expanded Memory Manager 386 Driver
;
; Module: SEGFIX - Sets the descriptor caches
;
; Version: 0.001
;
; Date: Feb 16,1990
;
; Author: Harish K. Naidu
;
;******************************************************************************
;
; Change log:
;
; DATE REVISION DESCRIPTION
; -------- -------- -------------------------------------------------------
; 02/16/89 Original
;
;******************************************************************************
;
; Functional Description:
;
;
;******************************************************************************
;******************************************************************************
; P U B L I C S
;******************************************************************************
public segfixup
;******************************************************************************
; D E F I N E S
;******************************************************************************
include vdmseg.inc
include desc.inc
SGDTD_GSEL equ 08h ; gdt data alias
SIDTD_GSEL equ 10h ; idt data alias
SVDMC_GSEL equ 18h ; VDM Code selector
SVDMD_GSEL equ 20h ; VDM Data Selector
;******************************************************************************
; E X T E R N A L R E F E R E N C E S
;******************************************************************************
LAST segment
extrn SetSegDesc:near
extrn SegTo24:near
LAST ends
SGDT segment
GDT_ENTRY 0, 0, 1, 0 ; null selector
GDT_ENTRY 0, 0, 0, D_DATA0 ; GDT alias
GDT_ENTRY 0, 0, 0, D_DATA0 ; IDT alias
GDT_ENTRY 0, 0, 0, D_CODE0 ; VDM Code
GDT_ENTRY 0, 0, 0, D_DATA0 ; VDM Data
SGDTLEN EQU $-SGDT
SGDT ends
SIDT segment
IDT_ENTRY 0, 0, 0
SIDTLEN EQU $-SIDT
SIDT ends
LAST segment
assume cs:LAST
SGDT_Ptr dd 2 dup (0) ; GDT ptr for LGDT
SIDT_Ptr dd 2 dup (0) ; IDT ptr for LIDT
Sreal_idt dw 0400h ; real mode DOS IDT limit
dd 0 ; and base ptr
dw 0 ; just in case qword used
ss_save dw ? ; temporary location to save stack
sp_save dw ?
;--------------------------------------------------------------------------
;
; Procedure SegFixup
;
; This routine will switch to protect mode and set up the selectors with
; real mode attributes and return to real mode. This is called at init
; time. This is necessary to fix up the BUGGY ROMS of certain machines
; like APRICOT Qi which does not do this for fs and gs. Therefore on this
; machine one cannot access fs from REAL MODE!! unless something similar
; to this routine is done
;
; USES: ALL
;--------------------------------------------------------------------------
segfixup proc near
mov ax,SGDT
mov es,ax ; ES:0 -> gdt
mov ax,SGDT
call SegTo24
mov cx,SGDTLEN
mov ah,D_DATA0
mov bx,SGDTD_GSEL
call SetSegDesc ; Set up SGDT alias descriptor
mov ax,SIDT
call SegTo24
mov cx,SIDTLEN
mov ah,D_DATA0
mov bx,SIDTD_GSEL
call SetSegDesc ; Set up SIDT alias descriptor
mov ax,seg LAST
call SegTo24
mov cx,0 ; 0 = 64K size
mov ah,D_CODE0
mov bx,SVDMC_GSEL
call SetSegDesc ; Set up LAST Code descriptor
mov ax,seg LAST
call SegTo24
mov cx,0 ; 0 = 64K size
mov ah,D_DATA0
mov bx,SVDMD_GSEL
call SetSegDesc ; Set up LAST Data descriptor
; The GDT and IDT pointers are setup up so that when CEMM gets turned on,
; the LGDT and LIDT instructions will have their correct pointers.
;
mov ax,SGDT ; DS:SI point to the GDT's entry location.
mov ds,ax
mov si,SGDTD_GSEL
mov ax,seg LAST ; ES:DI point to data strucutre used by the LGDT.
mov es,ax
assume es:LAST
mov di,offset LAST:SGDT_Ptr
movsd ; The 8 byte descriptor is copied over as is.
movsd
;
; Since only the first 6 bytes of the GDT pointer is needed for the base and
; linear address, the upper 8 bits of the linear address must be copied down
; to its proper location.
;
mov al,byte ptr es:[SGDT_Ptr][7]
mov byte ptr es:[SGDT_Ptr][5],al
;
; The exact same operations are done for the IDT pointer.
;
mov si,SIDTD_GSEL
mov di,offset LAST:SIDT_Ptr
movsd
movsd
mov al,byte ptr es:[SIDT_Ptr][7]
mov byte ptr es:[SIDT_Ptr][5],al
pushf
mov cs:[ss_save],ss
mov cs:[sp_save],sp
cli
;
; load gdt and ldt base registers (DB 66h needed for 32 bit address)
;
db 66h
lgdt fword ptr CS:[SGDT_ptr]
db 66h
lidt fword ptr CS:[SIDT_ptr]
;
; go protected and enable paging - turn on bits in CR0
;
mov eax,cr0
or eax, MSW_PROTECT ; or EAX,imm32
; PROT MODE
mov cr0,eax
; far jump to flush prefetch, and reload CS
db 0eah ; far jmp opcode
dw offset LAST:spm1 ; offset
dw SVDMC_GSEL ; selector
spm1:
; We are now in protected mode.
;
;
; Intel shows DS,ES,FS,GS,and SS set up to make sure 'Real Mode' type
; access rights, and limit are installed. In this program, that happens
; to already be the case, but for general purposeness, VDMD_GSEL fits
; the bill.
;
mov ax,SVDMD_GSEL ; selector with real mode attributes
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov gs,ax
;
; Switch back to real
;
;
; reset the PE bit ...
;
mov eax,cr0 ; get CR0
and eax,07FFFFFFEh ; force real mode and shut down paging
mov cr0,eax ; set CR0
; flush prefetched instructions with:
db 0EAh ; Far Jump opcode
dw offset LAST:srl386_b ; destination offset
dw LAST ; destination segment
srl386_b:
lidt fword ptr cs:[Sreal_idt]
mov ss, cs:[ss_save] ; restore stack
mov sp, cs:[sp_save]
mov eax,cr3 ; get CR3
mov cr3,eax ; set CR3 => clear TLB
popf
ret
segfixup endp
LAST ends
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?