• 进入保护模式(三)——《x86汇编语言:从实模式到保护模式》读书笔记17


    (十)保护模式下的栈

    76         ;以下用简单的示例来帮助阐述32位保护模式下的堆栈操作 
    77         mov cx,00000000000_11_000B         ;加载堆栈段选择子
    78         mov ss,cx
    79         mov esp,0x7c00

    第77~79行用来初始保护模式下的栈。栈段描述符是GDT中第3个(从0开始数)描述符,这个描述符的线性基地址是0x0000_0000,段界限是0x0000_7a00,粒度是字节,B=1,属于可读可写、向下扩展的数据段。

    我在博文数据段描述符和代码段描述符(一)——《x86汇编语言:从实模式到保护模式》读书笔记10中已经说过,

    对于向上扩展的段(E=0),逻辑地址中的偏移值范围可以从0到(界限值*粒度);

    对于向下扩展的段(E=1),逻辑地址中的偏移范围可以从(界限值*粒度)到0xFFFF(当B=0时)或者0xFFFF_FFFF(当B=1时)。

    所以,对于描述符中的栈段,偏移范围是0x0000_7a00~0xffff_ffff. 仔细琢磨一下,这和我们的想法不是那么一致,因为代码79行,令ESP的初值是0x7c00,也就是说,我们本打算定义一个偏移范围是0x0000_7a00~0x0000_7c00的栈段。

    因为线性基地址是0x0000_0000,也就是说描述符定义的栈段,实际可以访问的物理空间是0x0000_7a00~0xffff_ffff,但是我们却希望这个栈可以访问的物理空间是0x0000_7a00~0x0000_7c00。示意图(根据原书的图11-14改编而成)如下图所示。虽然这个栈不完美,但是不用担心,我们会在后面的学习中用更好的方法来创建栈。眨眼

    New0003栈

    (十一)验证32位下的栈操作

    隐式的栈操作(如push、pop、call、ret、iret等)涉及两个段,一个是指令所在的代码段,一个是栈段。之前的博文我们说过,对于可执行代码段,

    D=1:默认是32位地址和32位或8位的操作数

    D=0:默认是16位地址和16位或8位的操作数

    注意:指令前缀0x66可以用来选择非默认值的操作数大小;前缀0x67可以用来选择非默认值的地址大小

    对于栈段,

    B=1:栈指针使用ESP

    B=0:栈指针使用SP

    就本文的实验代码,其代码段描述符的D位是1,其栈段描述符的B位也是1. 所以,当进行隐式的栈操作时,默认是32位操作数(比如压栈的时候,压入的是双字),且用ESP进行操作。

    所以,下面的代码就用来验证这个事实。

    81         mov ebp,esp                        ;保存堆栈指针 
    82         push byte '.'                      ;压入立即数(字节)
    83         
    84         sub ebp,4
    85         cmp ebp,esp                        ;判断压入立即数时,ESP是否减4 
    86         jnz ghalt                          
    87         pop eax
    88         mov [0x1e],al                      ;显示句点 
    89      
    90  ghalt:     
    91         hlt                                ;已经禁止中断,将不会被唤醒

    在阅读这段代码的时候,我多少有点怀疑:书上说的到底是不是真的?我想通过实践来检验:探究一下PUSH指令在16位模式和32位模式下的执行规律。经过一番折腾,终于有了结果。请参考我的博文  16位模式/32位模式下PUSH指令探究——《x86汇编语言:从实模式到保护模式》读书笔记16

    第81行,复制esp的值给ebp;第82行,压入一个字节(byte关键字不能省略);理论上,把ebp的值减去4后(第84行),应该和此时esp的值相等。为了证明这一点,第85行比较ebp和esp的值,如果不相等,就跳转到91行执行停机指令;如果相等,就把字符“.”显示在之前的字符串后面。

    OK,第11章的内容已经学习完了。最后我们看一下代码的运行结果吧,结果就是在屏幕的左上角显示“Protect mode OK.”

    执行结果

    (完)

  • 相关阅读:
    圆珠笔芯为什么那么细
    2017第45周二
    浅谈XXE攻击
    谈谈ssrf
    htop简介
    关闭火狐定期向“http://detectportal.firefox.com/”发包
    linux登录用户(终端)间的通信
    linux下ftp、telnet的安装和使用
    深入解析hostname
    supervisor启动sqlmapapi失败 sqlmapapi: ERROR (file is not executable)
  • 原文地址:https://www.cnblogs.com/longintchar/p/5224396.html
Copyright © 2020-2023  润新知