• 第十七课 保护模式中的特权级(下)


    问题:

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

    不幸的事实:

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

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

    从高特权级的代码段通过return  far可以返回到低特权级的代码段执行。这时return  far是一个跳转指令,完成从高特权级到低特权级的跳转,这正是我们想要的。

    return的本质是做跳转的,而不是我们根深蒂固的做返回的。只是最常用的方式是做返回使用。

    思路整理:

      调用门的特权级跳转:

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

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

    retf的本质就是恢复cs和eip的值,因此,我们需要首先将cs和eip的值放入栈中。

    需要提前知道的事实:

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

      每一个特权级对应一个私有的栈(最多四个栈)

      特权级跳转变化之前必须指定好相应的栈

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

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

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

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

      4、指定目标代码段偏移(push)

      5、跳转(retf)

    实验1:

      1 %include "inc.asm"
      2 
      3 org 0x9000
      4 
      5 jmp ENTRY_SEGMENT
      6  
      7 [section .gdt]
      8 ; GDT definition
      9 ;                                 段基址,       段界限,       段属性
     10 GDT_ENTRY       :     Descriptor    0,            0,           0
     11 CODE32_DESC     :     Descriptor    0,    Code32SegLen  - 1,   DA_C + DA_32 + DA_DPL3
     12 VIDEO_DESC      :     Descriptor 0xB8000,       0x07FFF,       DA_DRWA + DA_32 + DA_DPL3
     13 DATA32_DESC     :     Descriptor    0,    Data32SegLen  - 1,   DA_DR + DA_32 + DA_DPL3
     14 STACK32_DESC    :     Descriptor    0,      TopOfStack16,    DA_DRW + DA_32 + DA_DPL3       
     15 ; GDT end
     16 
     17 GdtLen    equ   $ - GDT_ENTRY
     18 
     19 GdtPtr:
     20           dw   GdtLen - 1
     21           dd   0
     22           
     23           
     24 ; GDT Selector
     25 
     26 Code32Selector    equ (0x0001 << 3) + SA_TIG + SA_RPL3
     27 VideoSelector     equ (0x0002 << 3) + SA_TIG + SA_RPL3
     28 Data32Selector    equ (0x0003 << 3) + SA_TIG + SA_RPL3
     29 Stack32Selector   equ (0x0004 << 3) + SA_TIG + SA_RPL3
     30 
     31 ; end of [section .gdt]
     32 
     33 TopOfStack16    equ  0x7c00
     34 
     35 [section .s16]
     36 [bits 16]
     37 ENTRY_SEGMENT:
     38     mov ax, cs
     39     mov ds, ax
     40     mov es, ax
     41     mov ss, ax
     42     mov sp, TopOfStack16
     43     
     44     ; initialize GDT for 32 bits code segment
     45     mov esi, CODE32_SEGMENT
     46     mov edi, CODE32_DESC
     47     
     48     call InitDescItem
     49     
     50     mov esi, DATA32_SEGMENT
     51     mov edi, DATA32_DESC
     52     
     53     call InitDescItem
     54     
     55     mov esi, STACK32_SEGMENT
     56     mov edi, STACK32_DESC
     57     
     58     call InitDescItem
     59     
     60     ; initialize GDT pointer struct
     61     mov eax, 0
     62     mov ax, ds
     63     shl eax, 4
     64     add eax, GDT_ENTRY
     65     mov dword [GdtPtr + 2], eax
     66 
     67     ; 1. load GDT
     68     lgdt [GdtPtr]
     69     
     70     ; 2. close interrupt
     71     cli 
     72     
     73     ; 3. open A20
     74     in al, 0x92
     75     or al, 00000010b
     76     out 0x92, al
     77     
     78     ; 4. enter protect mode
     79     mov eax, cr0
     80     or eax, 0x01
     81     mov cr0, eax
     82     
     83     ; 5. jump to 32 bits code
     84     ; jmp dword Code32Selector : 0
     85     push Stack32Selector    ; mu biao zhan duan xuan ze zi
     86     push TopOfStack32       ; zhan ding zhi zhen wei zhi
     87     push Code32Selector     ; mu biao dai ma duan xuan ze zi
     88     push 0                     ; mu bioa dai ma duan pian yi
     89     retf
     90     
     91 
     92     
     93 ; esi    --> code segment label
     94 ; edi    --> descriptor label
     95 InitDescItem:
     96     push eax
     97     
     98     mov eax, 0
     99     mov ax, cs
    100     shl eax, 4
    101     add eax, esi
    102     mov word [edi + 2], ax
    103     shr eax, 16
    104     mov byte [edi + 4], al
    105     mov byte [edi + 7], ah
    106     
    107     pop eax
    108     
    109     ret
    110     
    111 [section .dat]
    112 [bits 32]
    113 DATA32_SEGMENT:
    114     DTOS                db    "D.T.OS!",0
    115     DTOS_OFFSET            equ    DTOS - $$
    116     
    117 Data32SegLen    equ        $ - DATA32_SEGMENT  
    118 
    119   
    120 [section .s32]
    121 [bits 32]
    122 CODE32_SEGMENT:
    123     mov ax, VideoSelector
    124     mov gs, ax
    125     
    126     mov ax, Data32Selector
    127     mov ds, ax
    128     
    129     mov ax, Stack32Selector
    130     mov ss, ax
    131     
    132     mov ax, Data32Selector
    133     mov ds, ax
    134     
    135     mov ebp, DTOS_OFFSET
    136     mov bx, 0x0C
    137     mov dh, 12
    138     mov dl, 33
    139     
    140     call PrintString
    141     
    142     jmp $
    143 
    144 
    145 ; ds:ebp   --> string address
    146 ; bx       --> attribute
    147 ; dx       --> dh : row, dl : col
    148 PrintString:
    149     push ebp
    150     push eax
    151     push edi 
    152     push cx
    153     push dx
    154     
    155 print:
    156     mov cl, [ds:ebp]
    157     cmp cl, 0
    158     je end
    159     mov eax, 80
    160     mul dh
    161     add al, dl
    162     shl eax, 1
    163     mov edi, eax
    164     mov ah, bl
    165     mov al, cl
    166     mov [gs:edi], ax
    167     inc ebp
    168     inc dl
    169     jmp print
    170     
    171 end:
    172     pop dx
    173     pop cx
    174     pop edi
    175     pop eax
    176     pop ebp
    177     
    178     ret
    179 
    180 Code32SegLen    equ    $ - CODE32_SEGMENT
    181 
    182 [section .gs]
    183 [bits 32]
    184 STACK32_SEGMENT:
    185     times 1024 * 4 db 0
    186 
    187 Stack32SegLen    equ    $ - STACK32_SEGMENT
    188 TopOfStack32    equ    Stack32SegLen - 1

    11-14行我们给每一个段加上了特权级DA_DPL3,同时26-29行也必须加上DA_RPL3。85-89是我们新添加的代码,运行结果如下:

    成功的从高特权级跳到了低特权级。

     将程序改成下面的样子可以得到同样的结果:

      1 %include "inc.asm"
      2 
      3 org 0x9000
      4 
      5 jmp ENTRY_SEGMENT
      6  
      7 [section .gdt]
      8 ; GDT definition
      9 ;                                 段基址,       段界限,       段属性
     10 GDT_ENTRY       :     Descriptor    0,            0,           0
     11 CODE32_DESC     :     Descriptor    0,    Code32SegLen  - 1,   DA_C + DA_32 + DA_DPL0
     12 VIDEO_DESC      :     Descriptor 0xB8000,       0x07FFF,       DA_DRWA + DA_32 + DA_DPL0
     13 DATA32_DESC     :     Descriptor    0,    Data32SegLen  - 1,   DA_DR + DA_32 + DA_DPL0
     14 STACK32_DESC    :     Descriptor    0,      TopOfStack16,    DA_DRW + DA_32 + DA_DPL0      
     15 ; GDT end
     16 
     17 GdtLen    equ   $ - GDT_ENTRY
     18 
     19 GdtPtr:
     20           dw   GdtLen - 1
     21           dd   0
     22           
     23           
     24 ; GDT Selector
     25 
     26 Code32Selector    equ (0x0001 << 3) + SA_TIG + SA_RPL0
     27 VideoSelector     equ (0x0002 << 3) + SA_TIG + SA_RPL0
     28 Data32Selector    equ (0x0003 << 3) + SA_TIG + SA_RPL0
     29 Stack32Selector   equ (0x0004 << 3) + SA_TIG + SA_RPL0
     30 
     31 ; end of [section .gdt]
     32 
     33 TopOfStack16    equ  0x7c00
     34 
     35 [section .s16]
     36 [bits 16]
     37 ENTRY_SEGMENT:
     38     mov ax, cs
     39     mov ds, ax
     40     mov es, ax
     41     mov ss, ax
     42     mov sp, TopOfStack16
     43     
     44     ; initialize GDT for 32 bits code segment
     45     mov esi, CODE32_SEGMENT
     46     mov edi, CODE32_DESC
     47     
     48     call InitDescItem
     49     
     50     mov esi, DATA32_SEGMENT
     51     mov edi, DATA32_DESC
     52     
     53     call InitDescItem
     54     
     55     mov esi, STACK32_SEGMENT
     56     mov edi, STACK32_DESC
     57     
     58     call InitDescItem
     59     
     60     ; initialize GDT pointer struct
     61     mov eax, 0
     62     mov ax, ds
     63     shl eax, 4
     64     add eax, GDT_ENTRY
     65     mov dword [GdtPtr + 2], eax
     66 
     67     ; 1. load GDT
     68     lgdt [GdtPtr]
     69     
     70     ; 2. close interrupt
     71     cli 
     72     
     73     ; 3. open A20
     74     in al, 0x92
     75     or al, 00000010b
     76     out 0x92, al
     77     
     78     ; 4. enter protect mode
     79     mov eax, cr0
     80     or eax, 0x01
     81     mov cr0, eax
     82     
     83     ; 5. jump to 32 bits code
     84     ; jmp dword Code32Selector : 0
     85     ; push Stack32Selector    ; mu biao zhan duan xuan ze zi
     86     ; push TopOfStack32       ; zhan ding zhi zhen wei zhi
     87     push Code32Selector     ; mu biao dai ma duan xuan ze zi
     88     push 0                     ; mu bioa dai ma duan pian yi
     89     retf
     90     
     91 
     92     
     93 ; esi    --> code segment label
     94 ; edi    --> descriptor label
     95 InitDescItem:
     96     push eax
     97     
     98     mov eax, 0
     99     mov ax, cs
    100     shl eax, 4
    101     add eax, esi
    102     mov word [edi + 2], ax
    103     shr eax, 16
    104     mov byte [edi + 4], al
    105     mov byte [edi + 7], ah
    106     
    107     pop eax
    108     
    109     ret
    110     
    111 [section .dat]
    112 [bits 32]
    113 DATA32_SEGMENT:
    114     DTOS                db    "D.T.OS!",0
    115     DTOS_OFFSET            equ    DTOS - $$
    116     
    117 Data32SegLen    equ        $ - DATA32_SEGMENT  
    118 
    119   
    120 [section .s32]
    121 [bits 32]
    122 CODE32_SEGMENT:
    123     mov ax, VideoSelector
    124     mov gs, ax
    125     
    126     mov ax, Data32Selector
    127     mov ds, ax
    128     
    129     mov ax, Stack32Selector
    130     mov ss, ax
    131     
    132     mov ax, Data32Selector
    133     mov ds, ax
    134     
    135     mov ebp, DTOS_OFFSET
    136     mov bx, 0x0C
    137     mov dh, 12
    138     mov dl, 33
    139     
    140     call PrintString
    141     
    142     jmp $
    143 
    144 
    145 ; ds:ebp   --> string address
    146 ; bx       --> attribute
    147 ; dx       --> dh : row, dl : col
    148 PrintString:
    149     push ebp
    150     push eax
    151     push edi 
    152     push cx
    153     push dx
    154     
    155 print:
    156     mov cl, [ds:ebp]
    157     cmp cl, 0
    158     je end
    159     mov eax, 80
    160     mul dh
    161     add al, dl
    162     shl eax, 1
    163     mov edi, eax
    164     mov ah, bl
    165     mov al, cl
    166     mov [gs:edi], ax
    167     inc ebp
    168     inc dl
    169     jmp print
    170     
    171 end:
    172     pop dx
    173     pop cx
    174     pop edi
    175     pop eax
    176     pop ebp
    177     
    178     ret
    179 
    180 Code32SegLen    equ    $ - CODE32_SEGMENT
    181 
    182 [section .gs]
    183 [bits 32]
    184 STACK32_SEGMENT:
    185     times 1024 * 4 db 0
    186 
    187 Stack32SegLen    equ    $ - STACK32_SEGMENT
    188 TopOfStack32    equ    Stack32SegLen - 1

    这个实验告诉我们:

    1、retf就是一个跳转指令,87-89行的代码与84行是等价的。

    2、在相同的特权级之间跳转时不需要栈发生变化的。

    3、特权级改变时一定要指定栈,要不然程序就会发生崩溃

    单步实验:

     首先用ndisasm -o 0x9000 loader > loader.txt进行反汇编,找到retf的断点位置0x90A6。

    启动bochs开始执行。

    运行到0x90A6时结果如下:

    可以看到此时cs寄存器的最后两位是0,这正是默认的特权级,继续执行。

    执行了retf过后,结果如下:

    此时cs的最后一个字节为b,可以算出最后两位为11,确实跳转到了特权级为3的代码段了。

    小结:

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

    利用远返回(retf)可以从高特权级转移到低特权级

    x86处理器每一个特权级对应一个私有的栈

    特权级跳转变化之前必须指定好相应的栈

  • 相关阅读:
    Centos7:Redis3.0集群搭建
    Centos7:Redis的安装,配置及使用
    nginx 配置反向代理和负载均衡
    Centos7:nginx的安装,配置及使用
    Centos7:dubbo监控中心安装,配置和使用
    Centos7:配置防火墙
    MarkDown常用语法
    关于获取本地系统时间是正确的,但插入数据库是错的,相差8小时
    Uncaught TypeError: Cannot read property 'getters' of undefined
    java mysql连接时出现的问题
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9623482.html
Copyright © 2020-2023  润新知