实践GDT和LDT
%include "pm.inc"
; 实践LDT
ORG 0100h
JMP REALMODE_START
; ########################################################################
; Define GDT
[SECTION .GDT]
GDT_BEGIN:
LABEL_DESC_NULL :Descriptor 0, 0, 0
LABEL_DESC_NORMAL :Descriptor 0, 0FFFFh, DA_DRW
LABEL_DESC_CODE32 :Descriptor 0, SegCode32Len - 1, DA_C + DA_32
LABEL_DESC_CODE16 :Descriptor 0, SegCode16Len - 1, DA_C
LABEL_DESC_DATA :Descriptor 0, SegDataLen - 1, DA_DRW
LABEL_DESC_STACK :Descriptor 0, TopOfStack, DA_DRWA + DA_32
LABEL_DESC_LDT :Descriptor 0, LDTLen - 1, DA_LDT
LABEL_DESC_VIDEO :Descriptor 0B8000h, 0FFFFh, DA_DRW
;GDTR
GDTLen EQU $ - $$
GDTPtr DW GDTLen - 1
DD 0
;Define GDT Selectors
SelNormal EQU LABEL_DESC_NORMAL - $$
SelCode32 EQU LABEL_DESC_CODE32 - $$
SelCode16 EQU LABEL_DESC_CODE16 - $$
SelData EQU LABEL_DESC_DATA - $$
SelStack EQU LABEL_DESC_STACK - $$
SelLDT EQU LABEL_DESC_LDT - $$
SelVideo EQU LABEL_DESC_VIDEO - $$
; THIS IS THE END OF DEFINATION OF GDT SEGMENT
; ########################################################################
; Define LDT
[SECTION .LDT]
ALIGN 32
LDT_BEGIN:
LABEL_LDT_DESC_CODE32 :Descriptor 0, LDTCodeLen - 1, DA_C + DA_32
LDTLen EQU $ - $$
SelLDTCode32 EQU LABEL_LDT_DESC_CODE32 - $$ + SA_TIL
; THIS IS THE END OF DEFINATION OF LDT SEGMENT
; ########################################################################
; Define 32 bits stack segment
[SECTION .STACK32]
ALIGN 32
[BITS 32]
STACK_BEGIN:
times 512 DB 0
TopOfStack EQU $ - $$ - 1
; THIS IS THE END OF DEFINATION OF 32 BITS STACK SEGMENT
; ########################################################################
; Define 32 bits data segment
[SECTION .DATA32]
ALIGN 32
[BITS 32]
DATA_BEGIN:
SPBakup DW 0 ;实模式下的SP值(备份)
PMMessage DB "In Protected Mode NOW!", 0
OffsetPMMessage EQU PMMessage - $$
TestString DB "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0
OffsetTestString EQU TestString - $$
SegDataLen EQU $ - $$
; THIS IS THE END OF DEFINATION OF 32 BITS DATA SEGMENT
; ########################################################################
; 16 bits real mode code segment
[SECTION .REALMODE]
[BITS 16]
REALMODE_START:
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV SP,100h
;###############DEBUG CODE########################
JMPSEG EQU 40H
MOV AX,JMPSEG
MOV DS,AX
MOV AX,[DS:0]
PUSH AX
MOV BYTE [DS:0],0CBH
PUSH CS
PUSH BACK
DB 0EAH
DW 0
DW JMPSEG
BACK:
POP AX
MOV [DS:0],AX
MOV AX,CS
MOV DS,AX
; Set real mode segment address and sp value
MOV [BACK_TO_REAL + 3], AX
MOV [SPBakup], SP
; Initialize 16 bits code segment descriptor
; This segment is used for jump back to real mode
XOR EAX,EAX
MOV AX,CS
SHL EAX,4
ADD EAX,READY_BACK_TO_REAL
MOV WORD [LABEL_DESC_CODE16 + 2],AX
SHR EAX,16
MOV BYTE [LABEL_DESC_CODE16 + 4],AL
MOV BYTE [LABEL_DESC_CODE16 + 7],AH
; Initialize 32 bits code segment descriptor
XOR EAX,EAX
MOV AX,CS
SHL EAX,4
ADD EAX,PROTECTMODE_START
MOV WORD [LABEL_DESC_CODE32 + 2],AX
SHR EAX,16
MOV BYTE [LABEL_DESC_CODE32 + 4],AL
MOV BYTE [LABEL_DESC_CODE32 + 7],AH
; Initialize 32 bits data segment descriptor
XOR EAX,EAX
MOV AX,CS
SHL EAX,4
ADD EAX,DATA_BEGIN
MOV WORD [LABEL_DESC_DATA + 2],AX
SHR EAX,16
MOV BYTE [LABEL_DESC_DATA + 4],AL
MOV BYTE [LABEL_DESC_DATA + 7],AH
; Initialize 32 bits stack segment descriptor
XOR EAX,EAX
MOV AX,CS
SHL EAX,4
ADD EAX,STACK_BEGIN
MOV WORD [LABEL_DESC_STACK + 2],AX
SHR EAX,16
MOV BYTE [LABEL_DESC_STACK + 4],AL
MOV BYTE [LABEL_DESC_STACK + 7],AH
; Initialize LDT segment descriptor in GDT
XOR EAX,EAX
MOV AX,CS
SHL EAX,4
ADD EAX,LDT_BEGIN
MOV WORD [LABEL_DESC_LDT + 2],AX
SHR EAX,16
MOV BYTE [LABEL_DESC_LDT + 4],AL
MOV BYTE [LABEL_DESC_LDT + 7],AH
; Initialize the segment descriptor in the LDT
XOR EAX,EAX
MOV AX,CS
SHL EAX,4
ADD EAX,LDTCODE32_START
MOV WORD [LABEL_LDT_DESC_CODE32 + 2],AX
SHR EAX,16
MOV BYTE [LABEL_LDT_DESC_CODE32 + 4],AL
MOV BYTE [LABEL_LDT_DESC_CODE32 + 7],AH
; Ready for load GDT into GDTR
XOR EAX,EAX
mov AX,CS
SHL EAX,4
ADD EAX,GDT_BEGIN
MOV DWORD [GDTPtr + 2],EAX
LGDT [GDTPtr]
; Disable Interupt
CLI
; Enable A20
IN AL, 92h
OR AL, 00000010b
OUT 92h,AL
; Enable protect mode
MOV EAX,CR0
OR EAX,1
MOV CR0,EAX
; JMP TO PROTECT MODE 32 BITS CODE SEGMENT!!!
JMP DWORD SelCode32:0
; PROTECT MODE BACK TO REAL MODE LANDING ZONE
LANDING_ZONE:
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV SP,[SPBakup]
; Disable A20
IN AL,92h
AND AL,11111101b
OUT 92h,AL
; Set interupt
STI
; EXIT
MOV AX,4C00h
INT 21h
; THIS IS THE END OF 16 BITS REAL MODE SEGMENT
; ########################################################################
; 32 bits segment in protect mode
[SECTION .CODE32]
ALIGN 32
[BITS 32]
PROTECTMODE_START:
MOV AX,SelData
MOV DS,AX
MOV AX,SelVideo
MOV GS,AX
MOV AX,SelStack
MOV SS,AX
MOV ESP,TopOfStack
;SHOW WE ARE ALREADY IN PROTECT MODE!
; Print string by write video memory directly
MOV AH,0Ch
XOR ESI,ESI
XOR EDI,EDI
MOV ESI, OffsetPMMessage
MOV EDI, (80 * 10 + 0) * 2
CLD
.1:
LODSB
TEST AL,AL
JZ .2
MOV [GS:EDI],AX
ADD EDI,2
JMP .1
.2:
call DisplayReturn
MOV AX, SelLDT
LLDT AX
; Jump into LDT 32 bits code segment
JMP SelLDTCode32:0
DisplayReturn:
PUSH EAX
PUSH EBX
MOV EAX, EDI
MOV BL, 160
DIV BL
AND EAX, 0FFH
INC EAX
MOV BL, 160
MUL BL
MOV EDI, EAX
POP EBX
POP EAX
RET
SegCode32Len EQU $ - $$
; THIS IS THE END OF 32 BITS PROTECT MODE SEGMENT
; ########################################################################
; LDT 32 BITS CODE SEGMENT
[SECTION .LDTCODE32]
ALIGN 32
[BITS 32]
LDTCODE32_START:
MOV AX, SelVideo
MOV GS, AX ; 视频段选择子(目的)
MOV EDI, (80 * 12 + 0) * 2 ; 屏幕第 10 行, 第 0 列。
MOV AH, 0Dh ; 0000: 黑底 1100: 红字
MOV AL, 'L'
MOV [GS:EDI], AX
; Ready back to real mode
JMP SelCode16:0
LDTCodeLen EQU $ - $$
; THIS IS THE END OF 32 BITS PROTECT MODE LDT CODE SEGMENT
; ########################################################################
; PROTECT MODE 16 BITS CODE SEGMENT
; USED FOR BACK TO REAL MODE
[SECTION .CODE16]
ALIGN 16
[BITS 32]
READY_BACK_TO_REAL:
MOV AX,SelNormal
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX
MOV EAX, CR0
AND EAX, 11111110b
MOV CR0, EAX
BACK_TO_REAL:
JMP 0:LANDING_ZONE
SegCode16Len EQU $ - $$
; THIS IS THE END OF 16 BITS PROTECT MODE CODE SEGMENT
; ########################################################################