现在的位置: 首页 > 综合 > 正文

一个操作系统的实现实验之3.2.4.5

2013年12月01日 ⁄ 综合 ⁄ 共 3080字 ⁄ 字号 评论关闭

目标:进入ring3

代码:pmtest5a.asm

原理:通过ret指令由高特权级转移到ring3级。注意我们的程序刚开始是运行在ring0级。

 

ring3是低特权级,需要通过ret命令进入。

 

1.因为我们要进入ring3,所以要添加一个ring3的代码段和ring3堆栈段

LABEL_DESC_CODE_RING3: Descriptor 0,SegCodeRing3Len-1, DA_C+DA_32+DA_DPL3

LABEL_DESC_STACK3:     Descriptor 0,      TopOfStack3, DA_DRWA+DA_32+DA_DPL3

DPL3表明该段是ring3

 

2.定义段的选择子

SelectorCodeRing3     equ     LABEL_DESC_CODE_RING3 - LABEL_GDT + SA_RPL3 ;=0x28+3=0x2b

SelectorStack3      equ     LABEL_DESC_STACK3 - LABEL_GDT + SA_RPL3     ;=0x40+3=0x43

 

3.段初始化

; 初始化Ring3描述符
 xor eax, eax
 mov ax, ds
 shl eax, 4
 add eax, LABEL_CODE_RING3
 mov word [LABEL_DESC_CODE_RING3 + 2], ax
 shr eax, 16
 mov byte [LABEL_DESC_CODE_RING3 + 4], al
 mov byte [LABEL_DESC_CODE_RING3 + 7], ah

; 初始化堆栈段描述符(Ring3)
 xor eax, eax
 mov ax, ds
 shl eax, 4
 add eax, LABEL_STACK3
 mov word [LABEL_DESC_STACK3 + 2], ax
 shr eax, 16
 mov byte [LABEL_DESC_STACK3 + 4], al
 mov byte [LABEL_DESC_STACK3 + 7], ah

 

4.定义堆栈段 ring3

[SECTION .s3]
ALIGN 32
[BITS 32]
LABEL_STACK3:
     times 512 db 0
TopOfStack3     equ     $ - LABEL_STACK3 - 1

 

5.定义代码段 ring3

[SECTION .ring3]
ALIGN 32
[BITS 32]
LABEL_CODE_RING3:
     mov ax, SelectorVideo
     mov gs, ax

     mov edi, (80 * 14 + 0) * 2
     mov ah, 0Ch
     mov al, '3'
     mov [gs:edi], ax

     jmp $
SegCodeRing3Len     equ     $ - LABEL_CODE_RING3

 

6.修改VIDEO段属性

由于ring3要写显存而访问VIDEO段,所以需要把他的DPL改为3

LABEL_DESC_VIDEO:      Descriptor 0B8000h,     0ffffh, DA_DRW+DA_DPL3

 

7.进入ring3

 push SelectorStack3
 push TopOfStack3
 push SelectorCodeRing3
 push 0
 retf    ;完成进入ring3的工作

 

8.bochs上运行pmtest5a

(0) [0x000000000003298a] 0010:0000003e (unk. ctxt): push 0x00000043           ; 6843000000

(0) [0x000000000003298f] 0010:00000043 (unk. ctxt): push 0x000001ff           ; 68ff010000

(0) [0x0000000000032994] 0010:00000048 (unk. ctxt): push 0x0000002b           ; 682b000000
(0) [0x0000000000032999] 0010:0000004d (unk. ctxt): push 0x00000000           ; 6800000000

push执行前

ss:0x0038, dh=0x00409303, dl=0x23e801ff, valid=7
        Data segment, base=0x000323e8, limit=0x000001ff, Read/Write, Accessed

esp: 0x000001ff 
 | STACK 0x000325e7 [0x00000000]
 | STACK 0x000325eb [0x00000000]
 | STACK 0x000325ef [0x00000000]
 | STACK 0x000325f3 [0x00000000]
 | STACK 0x000325f7 [0x00000000]
 | STACK 0x000325fb [0x00000000]

push执行后

ss:0x0038, dh=0x00409303, dl=0x23e801ff, valid=7
        Data segment, base=0x000323e8, limit=0x000001ff, Read/Write, Accessed

esp: 0x000001ef 
 | STACK 0x000325d7 [0x00000000]
 | STACK 0x000325db [0x0000002b]
 | STACK 0x000325df [0x000001ff]
 | STACK 0x000325e3 [0x00000043]
 | STACK 0x000325e7 [0x00000000]
 | STACK 0x000325eb [0x00000000]
此时的

cs:0x0010, dh=0x00409903, dl=0x294c007e, valid=1
        Code segment, base=0x0003294c, limit=0x0000007e, Execute-Only, Accessed, 32-bit

 

下面看看ret之后的变化
(0) [0x000000000003299e] 0010:00000052 (unk. ctxt): retf                      ; cb

cs:0x002b, dh=0x0040f903, dl=0x2a200014, valid=1
        Code segment, base=0x00032a20, limit=0x00000014, Execute-Only, Accessed, 32-bit
ss:0x0043, dh=0x0040f303, dl=0x25e801ff, valid=1
        Data segment, base=0x000325e8, limit=0x000001ff, Read/Write, Accessed
esp: 0x000001ff 511 ;栈的大小事512,所以esp=0x1ff
 | STACK 0x000327e7 [0x8ec88c00]
 | STACK 0x000327eb [0x8ec08ed8]
 | STACK 0x000327ef [0x0100bcd0]
 | STACK 0x000327f3 [0x8907b8a3]
 | STACK 0x000327f7 [0x8c017026]
 | STACK 0x000327fb [0xb70f66c8]
 我们看到retf执行后,cs和ss发生了变化,他们的值变成了ring3选择子的值。

抱歉!评论已关闭.