在前几节中的GDT和LDT中,大部分描述符的段界限都是0xffff,这其实是不严谨的,段界限是多少,要从实际出发,在这节中各个段的最后,都要定义一个宏表示此段的长度,在描述符中用此宏来表示段界限。
完整代码如下:
- %include "pm.inc"
- org 0100h
- jmp LABEL_BEGIN
- [section .gdt]
- LABEL_DESC_DUMMY:
- Descriptor 0,0,0
- LABEL_DESC_CODE32:
- Descriptor 0,GDT_Code32_Len - 1,DA_C | DA_32
- LABEL_DESC_CODE16:
- Descriptor 0,GDT_Code16_Len - 1,DA_C
- LABEL_DESC_VIDEO:
- Descriptor 0b8000h,0ffffh,DA_DRW
- LABEL_DESC_DATA:
- Descriptor 0,Data_Len - 1,DA_DRW
- LABEL_DESC_TEST:
- Descriptor 50000h,0ffffh,DA_DRW
- LABEL_DESC_STACK32:
- Descriptor 0,Stack_Len - 1,DA_DRW | DA_32
- LABEL_DESC_NORMAL:
- Descriptor 0,0ffffh,DA_DRW
- LABEL_DESC_LDT:
- Descriptor 0,LDT_LEN - 1,DA_LDT
- GDT_Len equ $ - LABEL_DESC_DUMMY
- GDT_Ptr:
- dw GDT_Len - 1
- dd 0
- Selector_Code32 equ LABEL_DESC_CODE32 - LABEL_DESC_DUMMY
- Selector_Code16 equ LABEL_DESC_CODE16 - LABEL_DESC_DUMMY
- Selector_Video equ LABEL_DESC_VIDEO - LABEL_DESC_DUMMY
- Selector_Data equ LABEL_DESC_DATA - LABEL_DESC_DUMMY
- Selector_Test equ LABEL_DESC_TEST - LABEL_DESC_DUMMY
- Selector_Stack32 equ LABEL_DESC_STACK32 - LABEL_DESC_DUMMY
- Selector_Normal equ LABEL_DESC_NORMAL - LABEL_DESC_DUMMY
- Selector_LDT equ LABEL_DESC_LDT - LABEL_DESC_DUMMY
- [section .ldt]
- LABEL_LDT:
- Descriptor 0,0,0
- LABEL_LDT_DESC_CODE32:
- Descriptor 0,LDT_Code32_Len - 1,DA_C | DA_32
- Selector_LDT_Code32 equ LABEL_LDT_DESC_CODE32 - LABEL_LDT + SA_TIL
- LDT_LEN equ $ - $$
- [section .stack32]
- [bits 32]
- LABEL_STACK32:
- times 512 db 0
- Stack_Len equ $ - $$
- [section .data]
- LABEL_DATA:
- _d_Disp_Pos dd 160 * 5
- d_Disp_Pos equ _d_Disp_Pos - $$
- _w_SP_Value_In_Real_Mode dw 0
- w_SP_Value_In_Real_Mode equ _w_SP_Value_In_Real_Mode - $$
- Data_Len equ $ - $$
- [section .s16]
- [bits 16]
- LABEL_BEGIN:
- mov ax,cs
- mov ds,ax
- mov es,ax
- mov ax,ss
- mov sp,0100h
- mov [LABEL_GO_BACK_TO_REAL + 3],ax
- Fill_Descriptor LABEL_DESC_CODE32,LABEL_CODE32
- Fill_Descriptor LABEL_DESC_CODE16,LABEL_BEGIN
- Fill_Descriptor LABEL_DESC_DATA,LABEL_DATA
- Fill_Descriptor LABEL_DESC_STACK32,LABEL_STACK32
- Fill_Descriptor LABEL_DESC_LDT,LABEL_LDT
- Fill_Descriptor LABEL_LDT_DESC_CODE32,LABEL_LDT_CODE32
- xor eax,eax
- mov ax,ds
- shl eax,4
- add eax,LABEL_DESC_DUMMY
- mov dword [GDT_Ptr + 2],eax
- lgdt [GDT_Ptr]
- mov [w_SP_Value_In_Real_Mode],sp
- cli
- in al,92h
- or al,00000010b
- out 92h,al
- mov eax,cr0
- or al,1
- mov cr0,eax
- jmp dword Selector_Code32:0
- _LABEL_PREPARE_GO_BACK_TO_REAL:
- LABEL_PREPARE_GO_BACK_TO_REAL equ _LABEL_PREPARE_GO_BACK_TO_REAL - $$
- mov ax,Selector_Normal
- mov ds,ax
- mov es,ax
- mov ss,ax
- mov sp,[w_SP_Value_In_Real_Mode]
- mov gs,ax
- mov fs,ax
- mov eax,cr0
- and al,11111110b
- mov cr0,eax
- LABEL_GO_BACK_TO_REAL:
- jmp 0:LABEL_ALREADY_REAL
- LABEL_ALREADY_REAL:
- in al,92h
- and al,11111101b
- out 92h,al
- sti
- mov ax,4c00h
- int 21h
- GDT_Code16_Len equ $ - $$
- [section .s32]
- [bits 32]
- LABEL_LDT_CODE32:
- mov ax,Selector_Video
- mov gs,ax
- mov ah,0ch
- mov al,'x'
- mov [gs:160 * 10],ax
- jmp Selector_Code16:LABEL_PREPARE_GO_BACK_TO_REAL
- LDT_Code32_Len equ $ - $$
- [section .s32]
- [bits 32]
- LABEL_CODE32:
- ;mov ax,Selector_Video
- ;mov gs,ax
- ;mov ah,0ch
- ;mov al,'x'
- ;mov [gs:80 * 10],ax
- mov ax,Selector_Stack32
- mov ss,ax
- mov esp,Stack_Len
- mov ax,Selector_Data
- mov ds,ax
- mov ax,Selector_Video
- mov gs,ax
- mov ax,Selector_Test
- mov fs,ax
- call Read_Test
- call Disp_Return
- call Write_Test
- call Read_Test
- mov ax,Selector_LDT
- lldt ax
- jmp Selector_LDT_Code32:0
- Read_Test:
- push ebp
- mov ebp,esp
- push ecx
- push esi
- mov ecx,8
- xor esi,esi
- .loop:
- mov al,[fs:esi]
- call Disp_Al
- inc esi
- loop .loop
- pop esi
- pop ecx
- pop ebp
- ret
- Write_Test:
- push ebp
- mov ebp,esp
- push eax
- push ecx
- push esi
- xor eax,eax
- mov eax,'A'
- xor esi,esi
- mov ecx,8
- .loop:
- mov [fs:esi],al
- inc esi
- inc eax
- loop .loop
- pop esi
- pop ecx
- pop eax
- pop ebp
- ret
- Disp_Al:
- push ebp
- mov ebp,esp
- push esi
- push ecx
- push eax
- mov ecx,2
- shr al,4
- .loop:
- and al,0fh
- cmp al,9
- jb .1
- add al,7
- .1:
- add al,30h
- mov esi,[d_Disp_Pos]
- mov byte [gs:esi],al
- mov byte [gs:esi + 1],0ch
- add dword [d_Disp_Pos],2
- dec ecx
- cmp ecx,0
- je .2
- pop eax
- jmp .loop
- .2:
- pop ecx
- pop esi
- pop ebp
- ret
- Disp_Return:
- push ebp
- mov ebp,esp
- push eax
- push ebx
- mov eax,[d_Disp_Pos]
- mov bl,160
- div bl
- and eax,0ffh
- inc ax
- mov bl,160
- mul bl
- mov [d_Disp_Pos],eax
- pop ebx
- pop eax
- pop ebp
- ret
- GDT_Code32_Len equ $ - $$
运行结果跟前一节一样。