Chinaunix首页 | 论坛 | 博客
  • 博客访问: 177810
  • 博文数量: 69
  • 博客积分: 2627
  • 博客等级: 少校
  • 技术积分: 715
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-24 22:37
文章分类

全部博文(69)

文章存档

2017年(3)

2014年(1)

2013年(4)

2012年(6)

2011年(21)

2010年(15)

2009年(19)

我的朋友

分类:

2010-04-22 17:06:44


长篇大论不多说了,最主要的是一点是通过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) |
0

上一篇:NFS开发环境

下一篇:EFLAGS

给主人留下些什么吧!~~