x86从实模式到保护模式 pdf_分页的实模式

AMD的 手册中(SVM部分)记录了这一模式,其实386就隐藏有这一模式,只能通过loadall指令来实现。386 loadall 指令操作码0xf,0x7,现在已被sysret指令占用。

loadall指令从ES:EDI(es:di)指定的内存中加载所有CPU状态值到CPU中。loadall指令不执行错误检测,CPL将设置为SS描述符条目的DPL。

LOADALL指令的详细介绍:

The LOADALL Instruction​www.rcollins.org

loadall指令使用的描述符格式:

使用loadall指令可以“创造”出一些奇特的模式,比如分页的实模式、32位实模式以及特权级3的实模式等等。这些奇他的模式都有一个问题:中断转移是按照实模式的中断方式进行的,栈指针使用SP,返回地址是按16位入栈的,EIP的高16位会被丢弃。不管那一种古怪的模式,有一点是不变的,那就是32位X86的保护机制是始终有效的。这些古怪的模式(包括实模式)都可以看做是保护模式的变种。

AMD的SVM在关闭嵌套页的情况下也支持一部分上面那些稀奇古怪的模式组合。有些组合在初始阶段还是挺有用。

暂时没有发现有什么模拟器能支持loadall指令,只能实机测试,AMD和intel的386基本上没问题,都支持。

;
; 386 loadall opcode=0x0f07
; 286               =0x0f05
; AMD64  0x0f07 = sysret
; nasm -fbin -o 
;
section .text vstart=0x7c00
bits 16        
start:
        cli
        xor     cx,cx
        mov     ds,cx
        mov     es,cx
        mov     ss,cx
        mov     sp,sp0
main:
        in      al,0x92
        or      al,2
        out     0x92,al

        mov     di,idt
        mov     cx,1024*2
        xor     ax,ax
        cld
        rep     stosw

page_pde        equ     0x5000
page_pte        equ     0x6000

        mov     di,0x5000
        mov     eax,page_pte | 7
        mov     [di],eax
        
        mov     di,0x6000
        mov     eax,0x7
        mov     cx,1024
p0:
        mov     [di],eax
        add     eax,0x1000
        lea     di,[di+4]
        loop    p0

        mov     eax,page_pde
        mov     cr3,eax

        mov     si,idt
        mov     eax,intx00
        mov     ecx,17
ii0:
        mov     [si],eax
        lea     si,[si +4]
        loop    ii0
        
         
        mov     edi,load_area
        call    set_load

        db      0xf,0x7			;装载处理器状态,进入32位分页实模式。

        hlt
bits 32
l_entry:
        cld
        call    dump
        mov     esi,buff
        mov     edi,0xb8000 +160*6

        call    putc        

;        ud2
        jmp     $

dump:
        mov     esi,msg
        mov     edi,buff
        mov     eax,cr0
        push    eax
        mov     eax,cr3
        push    eax
        jmp     dump.1
dump.0:
        stosb
dump.1:
        lodsb
        test    al,al
        jz      dump.4
        test    al,0x80
        jz      dump.0
        
dump.2:
        mov     dl,al
        pop     eax
        call    hex32

        test    dl,8    ;0xa end line
        jz     dump.3
        mov     al,0xa
        stosb
dump.3:
        mov     ax,0x2020
        stosw

        jmp     dump.1


dump.4:
        xor     al,al
        stosb
        ret
                

putc.0:
        mov     ah,2
        stosw
putc:
        lodsb
        test    al,al
        jnz     putc.0
        ret


hex32:
        push    eax
        shr     eax,16
        call    hex16
        pop     eax
hex16:
        push    eax
        shr     eax,8
        call    hex8
        pop     eax
hex8:
        push    eax
        shr     al,4
        call    hex81
        pop     eax
hex81:
        and     al,0fh
        add     al,30h
        cmp     al,39h
        jbe     hex82
        add     al,7h
hex82:
        stosb
        ret

intx00:
        mov     edi,0xb8000+160*8 - 32
        mov     eax,0x82418241
        mov     [edi],eax

        jmp     $

idtr    dw      256*4 - 1
        dd      idt

bits 16
set_load:
        mov     word [di+l_cr0 + 2],0x8000      ;PG=1,PE=0
        mov     byte [di + l_eflag],2			;IF = 0
        mov     ax,sp0
        mov     [di + l_esp],ax
        
        mov     ax,l_entry
        mov     [di + l_eip],ax					;入口
;
;  CS.G=SS.B = 1 ,32位代码段和32位堆栈段
;       
        mov     eax,0xc09300
        mov     [di + l_ss_ar],eax
        mov     [di + l_es_ar],eax
        mov     [di + l_ds_ar],eax

        mov     eax,0xc09b00
        mov     [di + l_cs_ar],eax

        mov     eax,-1
        mov     [di + l_cs_limit],eax
        mov     [di + l_ss_limit],eax
        mov     [di + l_es_limit],eax
        mov     [di + l_ds_limit],eax

        mov     ax,idt
        mov     [di + l_idt_base],ax
        mov     word [di + l_idt_limit],0x3ff
        ret
msg:
        db      "CR0="
        db      0x80
        db      "CR3="
        db      0x80
        db      0x80 | 8        ;打印控制字
        db      0
        times   510 - ($ - $$) db 0
        dw      0xaa55

section .bss      
idt:
        resb 256*4

;
; loadall 占用512字节,不是强制要求4字节对齐
;
align   4
load_area:
l_cr0   equ     0
l_eflag equ     4
l_eip   equ     8 
l_edi   equ     0xc
l_esi   equ     0x10
l_ebp   equ     0x14
l_esp   equ     0x18
l_ebx   equ     0x1c
l_edx   equ     0x20
l_ecx   equ     0x24
l_eax   equ     0x28
l_dr6   equ     0x2c
l_dr7   equ     0x30
l_tss_sel       equ     0x34    ;word 
l_ldtr_sel       equ     0x38   ;word
l_gs_sel        equ     0x3c
l_fs_sel        equ     0x40
l_ds_sel        equ     0x44
l_ss_sel        equ     0x48
l_cs_sel        equ     0x4c
l_es_sel        equ     0x50
l_tss_ar        equ     0x54
l_tss_base      equ     0x58
l_tss_limit     equ     0x5c

l_idt_ar        equ     0x60
l_idt_base      equ     0x64
l_idt_limit     equ     0x68

l_gdt_ar        equ     0x6c
l_gdt_base      equ     0x70
l_gdt_limit     equ     0x74

l_ldt_ar        equ     0x78
l_ldt_base      equ     0x7c
l_ldt_limit     equ     0x80

l_gs_ar        equ     0x84
l_gs_base      equ     0x88
l_gs_limit     equ     0x8c

l_fs_ar        equ     0x90
l_fs_base      equ     0x94
l_fs_limit     equ     0x98

l_ds_ar        equ     0x9c
l_ds_base      equ     0xa0
l_ds_limit     equ     0xa4

l_ss_ar        equ     0xa8
l_ss_base      equ     0xac
l_ss_limit     equ     0xb0

l_cs_ar        equ     0xb4
l_cs_base      equ     0xb8
l_cs_limit     equ     0xbc

l_es_ar        equ     0xc0
l_es_base      equ     0xc4
l_es_limit     equ     0xc8
        resb    512 - ($ - load_area)
        resb    0x1000
sp0:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值