OK,上一节跳转进了RING3,那么就可以利用调用门跳转到RING0了。还有一个问题,就是从特权级低的代码段跳转到特权级高的代码段,堆栈的地址必须从一个叫TSS(任务状态段)的段中取得,段基址保存在TR中,这个段其实也可看成一个数据结构,如图:
由于我们想跳转到RING0中,那么填充SS0,ESP0就好了,代码如下:
- [section .tss]
- align 32
- [bits 32]
- LABEL_TSS:
- dd 0
- dd Stack_Len
- dd Selector_Stack32
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dw 0
- dw $ - LABEL_TSS + 2
- db 0ffh
- TSS_Len equ $ - LABEL_TSS
接着在GDT中添加一个描述符和选择子来描述TSS,填充TSS的基地址也是必要的:
- LABEL_DESC_TSS:
- Descriptor 0,TSS_Len - 1,DA_386TSS
- ...
- Selector_TSS equ LABEL_DESC_TSS - LABEL_DESC_DUMMY
- Fill_Descriptor LABEL_DESC_TSS,LABEL_TSS
然后加载TR:
- call Read_Test
- call Disp_Return
- call Write_Test
- call Read_Test
- mov ax,Selector_TSS
- ltr ax
- push Selector_Ring3_Stack32
- push Ring3_Stack32_Len
- push Selector_Ring3_Code32
- push 0
- retf
OK,下面可以添加门描述符了,门描述符跟数据段或代码段描述符有点不同,结构如图所示:
由此图来添加一个Gate宏:
- ;%1 Selector
- ;%2 Offset
- ;%3 Para Count
- ;%4 Attr
- %macro Gate 4
- dw %2 & 0ffffh
- dw %1 & 0ffffh
- db %3 & 00011111b
- db %4 & 0ffh
- dw (%2 >> 16) & 0ffffh
- %endmacro
接着在GDT中添加一个描述符定义一个调用门,选择子也是必要的,由于是在RING3中使用调用门,所以描述符的DPL和选择子的RPL都要设置为3:
- LABEL_DESC_CALL_GATE:
- Gate Selector_Code32,LABEL_CALL_GATE_DEST,0,DA_386CGate + DA_DPL3
- ...
- Selector_Call_Gate equ LABEL_DESC_CALL_GATE - LABEL_DESC_DUMMY + SA_RPL3
标号LABEL_CALL_GATE_DEST,放在加载ldtr之前:
- push Selector_Ring3_Stack32
- push Ring3_Stack32_Len
- push Selector_Ring3_Code32
- push 0
- retf
- _LABEL_CALL_GATE_DEST:
- LABEL_CALL_GATE_DEST equ _LABEL_CALL_GATE_DEST - $$
- mov ax,Selector_LDT
- lldt ax
然后在RING3代码段中使用调用门,取代原来的死循环:
- ; jmp $
- call Selector_Call_Gate:0
OK,全部代码如下:
- %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 + DA_DPL3
- 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_RING3_STACK32:
- Descriptor 0,Ring3_Stack32_Len - 1,DA_DRW + DA_32 + DA_DPL3
- LABEL_DESC_RING3_CODE32:
- Descriptor 0,Ring3_Code32_Len - 1,DA_C + DA_32 + DA_DPL3
- LABEL_DESC_NORMAL:
- Descriptor 0,0ffffh,DA_DRW
- LABEL_DESC_LDT:
- Descriptor 0,LDT_Len - 1,DA_LDT
- LABEL_DESC_TSS:
- Descriptor 0,TSS_Len - 1,DA_386TSS
- LABEL_DESC_CALL_GATE:
- Gate Selector_Code32,LABEL_CALL_GATE_DEST,0,DA_386CGate + DA_DPL3
- 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 + SA_RPL3
- 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
- Selector_Ring3_Stack32 equ LABEL_DESC_RING3_STACK32 - LABEL_DESC_DUMMY + SA_RPL3
- Selector_Ring3_Code32 equ LABEL_DESC_RING3_CODE32 - LABEL_DESC_DUMMY + SA_RPL3
- Selector_TSS equ LABEL_DESC_TSS - LABEL_DESC_DUMMY
- Selector_Call_Gate equ LABEL_DESC_CALL_GATE - LABEL_DESC_DUMMY + SA_RPL3
- [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 .ring3_stack32]
- [bits 32]
- LABEL_RING3_STACK32:
- times 512 db 0
- Ring3_Stack32_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 .tss]
- align 32
- [bits 32]
- LABEL_TSS:
- dd 0
- dd Stack_Len
- dd Selector_Stack32
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dd 0
- dw 0
- dw $ - LABEL_TSS + 2
- db 0ffh
- TSS_Len equ $ - LABEL_TSS
- [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
- Fill_Descriptor LABEL_DESC_RING3_STACK32,LABEL_RING3_STACK32
- Fill_Descriptor LABEL_DESC_RING3_CODE32,LABEL_RING3_CODE32
- Fill_Descriptor LABEL_DESC_TSS,LABEL_TSS
- 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 * 14],ax
- jmp Selector_Code16:LABEL_PREPARE_GO_BACK_TO_REAL
- LDT_Code32_Len equ $ - $$
- [section .r3s32]
- [bits 32]
- LABEL_RING3_CODE32:
- mov ax,Selector_Video
- mov gs,ax
- mov ah,0ch
- mov al,'3'
- mov [gs:160 * 10],ax
- call Selector_Call_Gate:0
- Ring3_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_TSS
- ltr ax
- push Selector_Ring3_Stack32
- push Ring3_Stack32_Len
- push Selector_Ring3_Code32
- push 0
- retf
- _LABEL_CALL_GATE_DEST:
- LABEL_CALL_GATE_DEST equ _LABEL_CALL_GATE_DEST - LABEL_CODE32
- ; jmp $
- 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 $ - $$
运行结果如图所示: