长篇大论不多说了,最主要的是一点是通过ret,retf来实现高特权级向低特权级的转换.
调用ret,retf前要把低特权的SS,ESP,CS,EIP压入堆栈,然后就ret,retf,这里不需要tss这个东西.
软件环境: virtual pc + pcdos 7 + nasm 0.98.39
源码:
[section .text]
[org 0x100]
[bits 16]
start:
xor eax,eax
mov ax,cs
shl eax,4
mov ebx,eax ; cache
mov [gdt1+2],ax
mov [gdt3+2],ax
shr eax,16
mov [gdt1+4],al
mov [gdt3+4],al
mov [gdt1+7],ah
mov [gdt3+7],ah
; stack
lea eax,[ebx+stack0]
mov [gdt2+2],ax
shr eax,16
mov [gdt2+4],al
mov [gdt2+7],ah
lea eax,[ebx+stack3]
mov [gdt4+2],ax
shr eax,16
mov [gdt4+4],al
mov [gdt4+7],ah
; gdtr
lea eax,[ebx+gdt]
mov [gdtr+2],eax
lgdt [gdtr]
mov eax,cr0
or al,1
mov cr0,eax
cli
jmp RING0_CODE_SEL:do_pm
[bits 32]
do_pm:
mov ax,RING0_STACK_SEL
mov ss,ax
lea eax,[stack0_top]
mov esp,eax
mov ax,RING0_VIDEO_SEL
mov gs,ax
mov edi,(10 * 80 + 10) * 2 ; row 10 column 10
mov ah,0xC ; red color
mov al,'P'
mov [gs:edi],ax
push dword RING3_STACK_SEL
lea eax,[stack3_top]
push eax
push dword RING3_CODE_SEL
lea eax,[ring3]
push eax
retf
;ret 如果用ret,则不用将ring3的ss,esp压栈
ring3:
mov ax,RING3_VIDEO_SEL
mov gs,ax
mov edi,(10 * 80 +40) * 2 ; row 10 column 10
mov ah,0xA ; green color
mov al,'3'
mov [gs:edi],ax
jmp $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ALIGN 32
stack0: times 256 db 0
stack0_top:
ALIGN 32
stack3: times 256 db 0
stack3_top:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; GDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdt:
dw 0 ; null descriptor
dw 0
dw 0
dw 0
RING0_CODE_SEL equ $ - gdt
gdt1: dw 0xFFFF
dw 0
db 0
db 0x9A
db 0xCF
db 0
RING0_VIDEO_SEL equ $ - gdt
dw 0xFFFF
dw 0x8000
db 0x0b
db 0x92
db 0xCF
db 0
RING0_STACK_SEL equ $ - gdt
gdt2: dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
RING3_CODE_SEL equ $ - gdt + 3
gdt3: dw 0xFFFF
dw 0
db 0
db 0xFA
db 0xCF
db 0
RING3_VIDEO_SEL equ $ - gdt + 3
dw 0xFFFF
dw 0x8000
db 0x0b
db 0xF2
db 0xCF
db 0
RING3_STACK_SEL equ $ - gdt + 3
gdt4: dw 0xFFFF
dw 0
db 0
db 0xF2
db 0xCF
db 0
gdt_end:
gdtr: dw gdt_end - gdt - 1
dd 0
说明:
1. 共6个描述符,3个用于ring 0 (一个代码段,一个视频段,一个堆栈段),DPL,RPL均为0
3个用于ring 3(同样也是一个代码段,一个视频段,一个堆栈段),DPL,RPL均为3.
2. 程序首先为进入保护模式做准备,进入保护模式后,打印红色P
3. 向堆栈压入SS,ESP,CS,EIP,然后进入ring 3.
4. 进入ring 3的代码段后,显示一个绿色字符3,以证明确实进入了ring 3.
ring0 -> ring3 有着非常的意义,上述代码也不是唯一的方式.
阅读(1404) | 评论(0) | 转发(0) |