X86架构保护模式研究

最近在研究X86架构保护模式,记录下研究过程,然后写了一个汇编启动程序来验证保护模式下,指令执行方式。

 

提到保护模式就不得不提 “实模式”,当处理器加电后会从一个地址0xfff0执行一个跳转jmp指令到0x7c00地址处执行启动扇区指令,实模式下段寄存器长度为16位,一次只能寻址到64KB内存。

实模式下寻址方式:

段地址(存在段寄存器)*16+偏移来定位一个内存地址。

mov ax,0x0

mov ds,ax

mov byte [0x100],'a'

以上代码将'a' 写入地址 为ds:0x100的内存区域,那么这个地址为 0x0*16+0x100=0x100

进入保护模式后就不能通过这种方式寻址了。

保护模式寻址方式

段选择子加段内偏移

段段子子同样存放于段寄存器中,它不再是一个地址,而是一个索引,指向全局描述符表的某一项,GDT(全局描述符表)。

GDT 里面存放段描述符,段描述符里存放有段基址。

 

段描述符格式

以上是Intel手册中的关于全局描述符表和段描述符数据结构。

进入保护模式流程

1.设置GDT

2.设置CR0 ,PE位=1 进入保护模式

3.跳转到保护模式下指令(执行长跳转清空指令流

将汇编代码编译bin格式后,写入USB存储,通过在BIOS设置为USB启动,在电脑屏幕上显示LoadProect加载保护模式成功

保护模式汇编代码 保护模式测试代码

%define CODESEG 0x7c00 ;代码段地址

         mov word bx,ds:[gdt_table+CODESEG]

         ;描述符1 代码段描述符
         mov word [bx+8],0x0 ;段长度
         mov word [bx+10],0x7c00 ;段基址
         mov word [bx+12],0x9a00 
         mov word [bx+14],0xc0 ;段颗粒度 4KB

         ;创建#3描述符,保护模式下的堆栈段描述符
         mov dword [bx+0x18],0x00007a00
         mov dword [bx+0x1c],0x00409600

         ;GDTR表长度
         mov word [cs: gdt_addr+CODESEG],31  
                                 
         lgdt [cs: gdt_addr+CODESEG] ;加载GDTR地址到寄存器
      
         cli ;禁止中断

         ;开启保护模式
         mov eax,cr0
         or eax,1
         mov cr0,eax

        ;跳转至保护模式下代码 16段选择子:32位偏移
        jmp dword 0x0008:protect_start

    bits 32
    protect_start:
         mov cx,0x10 ;加载数据段
         mov ds,cx
         call clear_console
        
        ;向显示缓冲区写入 LoadProtect 以显示到屏幕上
        mov byte ds:[0],'L'
        mov word ds:[1],0x7
        mov byte ds:[2],'o'
        mov word ds:[3],0x7
        mov byte ds:[4],'a'
        mov word ds:[5],0x7
        mov byte ds:[6],'d'
        mov word ds:[7],0x7
        mov byte ds:[8],'P'
        mov word ds:[9],0x7
        mov byte ds:[10],'r'
        mov word ds:[11],0x7
        mov byte ds:[12],'o'
        mov word ds:[13],0x7
        mov byte ds:[14],'t'
        mov word ds:[15],0x7
        mov byte ds:[16],'e'
        mov word ds:[17],0x7
        mov byte ds:[18],'c'
        mov word ds:[19],0x7
        mov byte ds:[20],'t'
        mov word ds:[21],0x7
         jmp end
end:
    jmp end
;清空输出缓冲区
clear_console:
    push eax
    push edi

    xor eax,eax
    mov al,0x0
    mov ecx,0x500
    mov edi,0xb8000
    cld
    rep stosb

    pop edi
    pop eax
    ret

gdt_addr    dw 0x0;段限长度
gdt_table  dd (gdt+CODESEG);GDT的物理地址     
gdt:
    ;描述符0 空描述符
	dd 0x0,0x0
    
    ;代码段描述符
	dd 0x0,0x0

;显示缓冲区段描述符
view_seg:
    dw 0xffff ;段限长
    dw 0x8000 ;段基址 00-15
    db 0x0b ;段基地 16-23
    db 0x92;段属性 P-1 DPL-2 S-1 TYPE-4
    db 0x40;Segment Limit-4 AVL-1 L-1 DB-1 G-1
    db 0x0 ;段基址

times 510-($-$$) db 0
db 0x55,0xaa

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值