注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

编程学习

我的网上家园

 
 
 

日志

 
 

14章学习 3特权级的程序通过调用门调用0特权级的代码  

2013-04-07 17:03:00|  分类: 《x86汇编语言: |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
从高特权级的程序转移到低特权级的程序,可行的方法是 "假装" 从高特权级的代码返回到低特级的代码.
需要准备低特权级的栈段,代码段以及数据段,然后 把低特权级的栈选择子 栈指针ESP 低特权级的代码段选择子 代码执行偏移(EIP) 入栈,执行RETF 指令,即可转移到低特权级的代码执行.

低特权级的代码通过调用门调用高特权级的代码时,需要切换栈,TSS是必需的,LDT是可选的,可以把相关的代码段,数据段,栈段定义到GDT中.

以下代码演示了从0特权级代码转移到3特权级代码执行,3特权级代码通过 调用门调用0特级级代码(例程)的执行过程.
以下代码做为内核部分,需要通过第13章的MBR引导初始化代码从硬盘LBA 1扇区加载执行.


系统描述符中的D位无意义

;GDT表布局
;1# 4GB 内存段 (由MBR 代码初始化并创建) 固定
;2# MBR 代码段 (由MBR 代码初始化并创建) 固定
;3# 内核堆栈段 (由MBR 代码初始化并创建) 固定
;4# 显示缓冲区 (由MBR 代码初始化并创建) 固定
;5# 内核公共例程段 (由MBR 代码根据内核的信息创建)
;6# 内核数据段 (由MBR 代码根据内核的信息创建)
;7# 内核代码段 (由MBR 代码根据内核的信息创建)
;---------------------------------------以上部分由MBR主引导部分初始化生成
;8# 调用门(putstring公共例程) 1000_0_11B(请求RPL=3) -> 0x43 (调用门选择子)
;9#  3特权级数据段 1001_011B-> 0x4b
;10# 3特权级代码段 1010_011B-> 0x53
;11#  3特权级栈段 1011_011B-> 0x5b
;12#  TSS 1100_000B-> 0x60 TSS选择子




;常量定义
mem_0_4_gb_seg_sel equ 0x08 ;4GB内存段选择子
core_stack_seg_sel equ 0x18 ;内核栈段选择子
video_ram_seg_sel equ 0x20 ;显示缓冲区选择子
sys_routine_seg_se l equ 0x28 ;内核公共例程选择子
core_data_seg_sel equ 0x30 ;内核数据段选择子
core_code_seg_sel equ 0x38 ;内核代码段选择子
call_putstring_sel equ 0x43 ;调用门选择子
core_3_data_sel equ 0x4b ;3特权级数据段选择子
core_3_code_sel equ 0x53 ;3特权级代码段选择子
core_3_stack_sel equ 0x5b ;3特权级栈段选择子
tss_seg_sel equ 0x60 ;TSS选择子


;内核头部段
section header vstart=0
;=========================================================================
core_length dd core_end
core_sys_seg dd section.sys.start
core_data_seg dd section.data.start
core_code_seg dd section.code.start
entry dd start
dw core_code_seg_sel
;公共例程段
[bits 32]
section sys vstart=0
;=========================================================================
;入口参数 DS:EBX 指向字符串所在位置 显示字符串到屏幕上.
putstring:
push ecx
.show:
mov cl,[ebx]
or cl,cl
jz .exit
call putchar
inc ebx
jmp .show
.exit:
pop ecx
retf

putchar:
pushad
mov dx,0x3d4
mov al,0xe
out dx,al
inc dx
in al,dx
mov ah,al
dec dx
mov al,0xf
out dx,al
inc dx
in al,dx ;AX=当前光标位置
cmp cl,0xd
jnz .0xa
xor dx,dx
mov bx,80
div bx
mul bx
jmp .setcursor
.0xa:
cmp cl,0xa
jnz .ch
add ax,80
cmp ax,25*80
jb .setcursor
sub ax,80
jmp .rollscreen
.ch:
push es
mov ebx,video_ram_seg_sel
mov es,ebx
movzx ebx,ax
shl ebx,1
mov [es:ebx],cl
pop es
inc ax
cmp ax,25*80
jb .setcursor
mov ax,24*80


.rollscreen:
push ds
push es
mov ebx,video_ram_seg_sel
mov ds,ebx
mov es,ebx
mov esi,1*80*2
xor edi,edi
mov ecx,24*80*2/4
cld
rep movsd
mov esi,80*24*2
mov ecx,80*2/4
.clr:
mov dword [esi],0x07200720
add esi,4
loop .clr
pop es
pop ds

.setcursor:
mov bx,ax
mov dx,0x3d4
mov al,0xe
out dx,al
inc dx
mov al,bh
out dx,al
dec dx
mov al,0xf
out dx,al
inc dx
mov al,bl
out dx,al
popad
ret

;入口参数 EDX:EAX=描述符
;返回参数 CX-> 新安装的描述符选择子
set_up_gdt_descriptor:
push eax
push ebx
push edx
push ds
push es
mov ebx,core_data_seg_sel
mov ds,ebx
mov ebx,mem_0_4_gb_seg_sel
mov es,ebx
sgdt [pgdt]
mov bx,[pgdt]
movzx ecx,bx
inc cx
add ecx,[pgdt+2]
mov [es:ecx],eax
mov [es:ecx+4],edx
add bx,8
mov [pgdt],bx
lgdt [pgdt]
mov ax,bx
xor dx,dx
mov bx,8
div bx
mov cx,ax
shl cx,3
pop es
pop ds
pop edx
pop ebx
pop eax
retf

;输入:EAX=线性基地址 EBX=段界限 ECX=属性 ;返回:EDX:EAX=描述符
make_seg_descriptor:                       
mov edx,eax
shl eax,16
or ax,bx                         
and edx,0xffff0000             
rol edx,8
bswap edx                          
and ebx,0xf0000
or edx,ebx                     
or edx,ecx                  
retf


;入口参数: EAX=目标代码 32位的偏移量 BX=目标代码 段选择子 CX=调用门属性
;返回参数: EDX:EAX 生成的64位调用门描述符 EDX是高32位,EAX是低32位
make_gate_descriptor:
push ebx
mov edx,eax
xor dx,dx ;或者 and edx,0xffff0000
or dx,cx ;生成调用门描述符的高32位 
shl ebx,16
and eax,0xffff
or eax,ebx
pop ebx
retf ;远调用过程


;内存分配例程 入口参数: ECX=要申请的内存大小 返回ECX=申请到的内存基地址
allocate_memory:
push eax
push ebx
push ds
mov eax,core_data_seg_sel
mov ds,eax
mov eax,[ram_alloc]
add eax,ecx
mov ecx,[ram_alloc]
mov ebx,eax
and ebx,0xfffffffc
add ebx,4
test eax,3
cmovnz eax,ebx
mov [ram_alloc],eax
pop ds
pop ebx
pop eax
retf

section data vstart=0
;=========================================================================
   pgdt: dw 0
dd 0
ram_alloc:   dd 0x100000
   message: db 0xd,0xa,'Core is running.',0xd,0xa,0
message2: db 'call gate test.',0xd,0xa,0
message3: db 0xd,0xa,'Core 3 is running!',0

section code vstart=0
;=========================================================================
start:

mov eax,core_data_seg_sel
mov ds,eax
mov ebx,message
call sys_routine_seg_sel:putstring ;显示内核正在运行

mov eax,putstring ;EAX=代码在段内的偏移量
mov bx,sys_routine_seg_sel ;BX=目标代码段选择子(内核公共例程段)
mov cx,0xec00 ;调用门属性 1110_1100_000_00000B -> 0xec00
call sys_routine_seg_sel:make_gate_descriptor
call sys_routine_seg_sel:set_up_gdt_descriptor ;安装putstring调用门

mov ebx,message2 ;测试调用门
call call_putstring_sel:0 ;call 0x43:0  0特权级代码通过调用门显示字符串 CPL=0 RPL=3
sgdt [pgdt]
mov esi,[pgdt+0x2] ;取得GDT的基地址

mov eax,mem_0_4_gb_seg_sel
mov es,eax ;ES->4GB 内存空间

mov eax,[es:esi+48] ;EAX=内核数据段描述符低32位
mov edx,[es:esi+52] ;EDX=内核数据段描述符高32位
or edx,0x6000 ;修改内核数据段的特权级为3
call sys_routine_seg_sel:set_up_gdt_descriptor ;安装3特权级数据段

mov eax,[es:esi+56] ;EAX=内核代码段描述符低32位
mov edx,[es:esi+60] ;EDX=内核代码段描述符高32位
or edx,0x6000 ;修改内核代码段的特权级为3
call sys_routine_seg_sel:set_up_gdt_descriptor ;安装3特权级代码段

mov ecx,4096 ;4KB栈空间
call sys_routine_seg_sel:allocate_memory ;申请分配4KB的栈空间
add ecx,4096
mov eax,ecx ;栈起始线性地址
mov ebx,0xffffe ;栈界限
mov ecx,0xc0f600 ;属性 3特权级 1100_0000_1110_0110_00000000B
call sys_routine_seg_sel:make_seg_descriptor
call sys_routine_seg_sel:set_up_gdt_descriptor ;安装3特权级栈段

mov ecx,104 ;申请104字节的TSS空间
call sys_routine_seg_sel:allocate_memory

;以下构造TSS
mov word [es:ecx+0x0],0 ;TSS前一个任务的指针=0
mov dword [es:ecx+0x4],0 ;0特权级ESP=0
mov dword [es:ecx+0x8],core_stack_seg_sel ;0特权级栈选择子

mov word [es:ecx+96],0 ;LDT=0
mov word [es:ecx+100],0 ;T位=0
mov word [es:ecx+102],103 ;TSS界限 TSS大小减1


mov eax,ecx ;TSS基地址
mov ebx,103 ;TSS界限
mov ecx,0x408900 ; DPL=0 的TSS描述符
call sys_routine_seg_sel:make_seg_descriptor
call sys_routine_seg_sel:set_up_gdt_descriptor ;安装TSS描述符

ltr cx ;TSS描述符选择子


push core_3_stack_sel
push 0
push core_3_code_sel
push core_3_start
retf

core_3_start:
mov eax,core_3_data_sel
mov ds,eax
mov ebx,message3
call call_putstring_sel:0

jmp $

section end 
core_end:
  评论这张
 
阅读(20)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017