保护模式中的特权级(下)

使用调用门如何实现不同特权级代码之间的跳转(如:从高特权级到低特权级)?

调用门只支持从低特权级跳转到高特权级执行。

无法利用调用门从高特权级跳转到低特权级执行。

调用门的特权级跳转分析

1. 通过远调用(call far) : 低特权级  --> 高特权级

2. 通过远返回(retf) : 高特权级 --> 低特权级

函数的调用过程

需要提前知道的事实

1. x86处理器对于不同的特权级需要使用不同的栈。

2. 每一个特权级对应一个私有的栈(最多4个栈)。

3. 特权级跳转之前需要指定好相应的栈

解决方案(高特权级 --> 低特权级)

1. 指定目标栈段选择子(push)

2. 指定栈顶指针位置(push)

3. 指定目标代码段选择子(push)

4. 指定目标代码段偏移地址(push)

5. 跳转(retf)

%include "inc.asm"

org 0x9000

jmp ENTRY_SEGMENT

[section .gdt]
; GDT definition
;                                 段基址,       段界限,       段属性
GDT_ENTRY		: Descriptor		0, 			    0,		      0
CODE32_DESC		: Descriptor		0, 	   Code32SegLen - 1,  DA_32 + DA_C + DA_DPL3
VIDEO_DESC	    : Descriptor     0xb8000,       0x7fff,       DA_32 + DA_DRWA + DA_DPL3
DATA32_DESC		: Descriptor	    0,     Data32SegLen - 1,  DA_32 + DA_DR + DA_DPL3
STACK32_DESC	: Descriptor        0,      TopOfStack32,     DA_32 + DA_DRW + DA_DPL3
; GDT end  

GdtLen	  equ	   $ - GDT_ENTRY
GdtPtr:    
		dw	GdtLen - 1
		dd	0

; GDT Selector
Code32Selector	equ    (0x0001 << 3) + SA_TIG + SA_RPL3
VideoSelector	equ    (0x0002 << 3) + SA_TIG + SA_RPL3
Data32Selector  equ    (0x0003 << 3) + SA_TIG + SA_RPL3
Stack32Selector equ    (0x0004 << 3) + SA_TIG + SA_RPL3
; end of [section .gdt]

TopOfStack16	equ    0x7c00

[section .dat]
[bits 32]
DATA32_SEGMENT:
	DTOS		        db    "D.T.OS!", 0
	DTOS_Offset	        equ	  DTOS - $$ 

	HELLOWORLD		    db    "Hello, World!", 0
	HELLOWORLD_Offset   equ   HELLOWORLD - $$

Data32SegLen	equ   $ - DATA32_SEGMENT

[section .s16]
[bits 16]
ENTRY_SEGMENT:
	mov ax, cs
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov sp, TopOfStack16

	; initialize GDT for 32 bits code segment
	mov esi, CODE32_SEGMENT
	mov edi, CODE32_DESC
	call InitDescItem

	mov esi, DATA32_SEGMENT
	mov edi, DATA32_DESC
	call InitDescItem

	mov esi, STACK32_SEGMENT
	mov edi, STACK32_DESC
	call InitDescItem

	; initalize GDT pointer struct
	mov eax, 0
	mov ax, ds
	shl eax, 4
	add eax, GDT_ENTRY
	mov dword [GdtPtr + 2], eax

	; 1. load GDT
    lgdt [GdtPtr]
    
    ; 2. close interrupt
    cli 
    
    ; 3. open A20
    in al, 0x92
    or al, 00000010b
    out 0x92, al
    
    ; 4. enter protect mode
    mov eax, cr0
    or eax, 0x01
    mov cr0, eax
    
    ; 5. jump to 32 bits code
    ; jmp dword Code32Selector : 0

	push Stack32Selector			; 目标栈段选择子
	push TopOfStack32				; 目标栈顶指针
	push Code32Selector				; 目标代码段选择子
	push 0							; 目标代码段偏移
	retf

; esi    --> code segment labelBACK_ENTRY_SEGMENT
; edi    --> descriptor label
InitDescItem:
	push eax

	mov eax, 0
	mov ax, cs
	shl eax, 4
	add eax, esi
	mov word [edi + 2], ax
	shr eax, 16
	mov byte [edi + 4], al
	mov byte [edi + 7], ah
	
	pop eax

	ret

[section .s32]
[bits 32]
CODE32_SEGMENT:
	mov ax, VideoSelector
	mov gs, ax

	mov ax, Stack32Selector
	mov ss, ax

	mov eax, TopOfStack32
	mov esp, eax

	mov ax, Data32Selector
	mov ds, ax

	mov ebp, DTOS_Offset
	mov bx, 0x0c
	mov dh, 13
	mov dl, 33
	call PrintString

	mov ebp, HELLOWORLD_Offset
	mov bx, 0x0c
	mov dh, 14
	mov dl, 30
	call PrintString
	
	jmp $

; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:
	push ebp
	push cx
	push eax
	push dx
	push edi

print:
	mov cl, [ds:ebp]
	cmp cl, 0
	je end
	mov eax, 80
	mul dh
	add al, dl
	shl eax, 1
	mov edi, eax
	mov ah, bl
	mov al, cl
	mov [gs:edi], ax
	inc ebp
	inc dl
	jmp print
	
end:
	pop edi
	pop dx
	pop eax
	pop cx
	pop ebp

	ret

Code32SegLen	equ    $ - CODE32_SEGMENT


[section .gs]
[bits 32]
STACK32_SEGMENT:
	times 1024 * 4 db 0

Stack32SegLen	equ    $ - STACK32_SEGMENT
TopOfStack32    equ    Stack32SegLen - 1

10-14行,23-26行我们分别把段描述符的DPL改为3,选择子的RPL改为3.

90-94行来实现从高特权级到低特权级的跳转。

我们通过打断点的方式来查看cs段寄存器的值,看看我们是否从高特权级跳转到低特权级。

 在retf跳转之前,cs段寄存器的值为0,cs段寄存器的后两位为CPL(当前可执行代码段的特权级),后2位为0则说明当前位于0特权级,也说明了处理器默认的CPL为0。

 retf执行完以后,cs段寄存器的值为0x00b,转换为2进制就是1011b,最后两位为11,则说明了此时处理器的CPL为3(最低特权级),这和我们设置的特权级时一样的。

 其他结论

第一个实验

我们把90行和91行注释掉,运行后发现处理器出现了异常,这是因为从高特权级跳转到低特权级时,没有给它指定相应特权级的栈段。

第二个实验

我们将所有段描述符和选择子的特权级都改为0,然后注释掉90行和91行,程序正常的打印出了字符串,则说明在相同特权级代码段间执行跳转时,不需要指定目标栈的选择子和栈顶指针位置。此时92行-94行的作用和88行的作用是一样的,都能正常的跳转过去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值