zoukankan      html  css  js  c++  java
  • 操作系统-保护模式中的特权级下

    Q:使用调用门如何实现不同特权级之间的跳转?(从高到低)
    在实际的使用中,调用门只支持从低特权级到高特权级执行,无法利用调用门从高特权级跳转到低特权级执行
    A.调用门的特权级跳转分析
    操作系统-保护模式中的特权级下
    左边代码段为低特权级代码段,利用调用门以及call指令(远调用)可以进入右边高特权级代码段,最后利用return (跳转指令)far返回低代码段。
    实现思路
    调用门的特权级跳转-通过远调用(call far):低特权级到高特权级;通过远返回(retf):高特权级到低特权级。
    调用过程(近调用)如下
    操作系统-保护模式中的特权级下
    左边代码将ax bx寄存器值压入栈,通过call指令直接调用段中func函数,call之后程序转入func入口处执行,在此过程中,eip寄存器会被压入栈中,当ret指令执行时,从栈顶将eip寄存器之前的值拿出,恢复到eip寄存器中,执行完毕,程序执行流成功执行。
    相同理,远调用一样,
    操作系统-保护模式中的特权级下
    实现过程
    1.在实现之前需要知道的是,x86处理器对于不同的特权级需要使用不同的栈,每一个特权级对应一个私有栈,特权级跳转变化之前必须指定好相应的栈
    2.从高特权级到低特权级实现:指定目标栈段选择子,指定栈顶指针位置,指定目标代码段选择子,指定目标代码段偏移,最后进行跳转
    代码如下

    %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_C + DA_32 + DA_DPL3
    VIDEO_DESC      :     Descriptor 0xB8000,     0x07FFF,         DA_DRWA + DA_32 + DA_DPL3
    DATA32_DESC     :     Descriptor    0,    Data32SegLen - 1,    DA_DR + DA_32 + DA_DPL3
    STACK32_DESC    :     Descriptor    0,     TopOfStack32,       DA_DRW + DA_32 + 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 .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
    
        ; initialize 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 label
    ; 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 .dat]
    [bits 32]
    DATA32_SEGMENT:
        DTOS               db  "D.T.OS!", 0
        DTOS_OFFSET        equ DTOS - $$
    
    Data32SegLen equ $ - DATA32_SEGMENT
    
    [section .s32]
    [bits 32]
    CODE32_SEGMENT:
        mov ax, VideoSelector
        mov gs, ax
    
        mov ax, Data32Selector
        mov ds, ax
    
        mov ax, Stack32Selector
        mov ss, ax
    
        mov eax, TopOfStack32
        mov esp, eax
    
        mov ebp, DTOS_OFFSET
        mov bx, 0x0C
        mov dh, 12
        mov dl, 33
    
        call PrintString;打印
    
        jmp $
    
    ; ds:ebp    --> string address
    ; bx        --> attribute
    ; dx        --> dh : row, dl : col
    PrintString:
        push ebp
        push eax
        push edi
        push cx
        push dx
    
    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 dx
        pop cx
        pop edi
        pop eax
        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
    

    代码实现结果
    操作系统-保护模式中的特权级下
    为了更好了解从高特权级到低特权级的转换,首先通过反编译找到关键的跳转指令,并设置断点进行单步调试,如图所示,在跳转之前查看寄存器cx值,发现最后2为0,继续单步调试,在程序跳转到[section .s32][bits 32]部分时,再对寄存器进行查看,发现此时cx寄存器的值的二级制最后两位11,为3。此时可以得知从高特权级到低特权级进行了转移。
    操作系统-保护模式中的特权级下操作系统-保护模式中的特权级下操作系统-保护模式中的特权级下
    小结
    1.调用门只支持从低特权级跳转到高特权级执行
    2.利用远返回(retf)可以从高特权级转移到低特权级
    3.x86处理器中每一个特权级对应一个私有的栈
    4.特权级跳转之前必须指定好相应的栈

  • 相关阅读:
    json-c初探(一)
    Java程序员跳槽的首选面试题最新合集(2021下半年),初中高级程序员!
    R语言版本的bedtools--bedtoolsr
    使用R语言(cpm包)进行序列变点(change point)检测
    三款PHP大马,已解密、去后门
    php 取出数据表数据放入数组并排序
    VimTutor每讲小结
    记录一下c++学习过程
    vmware fusion关闭自动挂起(suspend)的方法
    mac中安装mysqlclient出错error: command 'clang' failed with exit status 1的解决办法
  • 原文地址:https://www.cnblogs.com/aiaitie/p/12772311.html
Copyright © 2011-2022 走看看