zoukankan      html  css  js  c++  java
  • ESP、EBP、CALL 指令与局部变量浅析

    概述

        函数调用是计算机程序中一个最重要的概念之一,从汇编的角度看,能更加直观地理解函数调用的原理,理解 CALL 指令调用过程中 ESP、EBP 寄存器的作用。

        我们先从一段简陋的 C 语言代码说起,我们首先调用了 printf 函数,为什么要调用 printf 函数呢?实际上是为了更方便地在 OllyDBG 反汇编工具中断点,能更好地定位到 fun 函数的位置(因为 fun 函数的 CALL 将紧跟着 printf 函数的 CALL)。

    在 fun 函数中,我们定义两个 int 型变量(两个 4 字节的变量),给 a 赋值了 0,给 b 赋值了 2。

    image

    我们用 OllyDBG 载入,在 printf 函数处下断点,运行在断点处暂停下来,在堆栈窗口中按 Enter 跟随到反汇编处,我们来到了下图所示的位置,第一行就是 main 函数这个 CALL 的段首,首先把 EBP 压栈,为了保存外层代码的 EBP 的值,使这个 CALL 不影响外层代码的 EBP 的值。然后第二行,程序将 ESP 赋值给 EBP。此时,EBP 与 ESP 重合。

    第三行是一个 PUSH 指令,它将指向字符串的指针压栈,这个指针指向的是“this is a break point”字符串,第四行程序执行 CALL 指令调用 printf 函数,printf 函数将从堆栈中取出参数进行处理,最终在终端中打印出字符串。换言之,参数通过堆栈传递给 printf 函数,就像 C 语言那样。

    image

    第五行将 ESP 增加了 4,然后下一行程序直接 CALL 了 fun 函数。我们按 Enter 键跟进到 fun 函数内部,如下图。

    image

    在 fun 函数内部,EBP 又被压栈,然后 EBP 被赋值成 ESP 的值(有点像之前 main 函数段首的情形)

    注意第三行,ESP 被减少了 8,这样的话,EBP 就比 ESP 多 8。第四行与第五行是 MOV 赋值指令,首先立即数 0 赋值给了 EBP – 4 的位置,然后立即数 2 赋值给了 EBP – 8 的位置。

    让我们来仔细分析一下,不难看出,ESP 减少 8,使得 ESP 与 EBP 相隔 8 字节的地址位置,换言之,ESP 与 EBP 中间有 8 字节的空隙,此时 ESP 比 EBP 小 8。而接下来的两行 MOV 指令将 EBP – 4 这个地址,EBP – 8 这个地址,分别赋值了 0 和 2,这两个 4 字节的 int 整数型数据,a 和 b 两个局部变量刚好填满了 ESP 与 EBP 中间 8 字节的空隙。我们可以作图理解它的结构:

    image

    局部变量的堆栈赋值完成以后,函数的基本功能就执行完了。这时,ESP 被赋值成 EBP 的值(跟 fun 函数开头刚好相反,开头是 EBP 被赋值成 ESP) ,相当于将 ESP 还原函数调用之前的状态。下一行,从堆栈中弹出 EBP 的值(也就是 fun 函数开头 PUSH 的 EBP 值),也相当于将 EBP 还原成函数调用之前的状态,最后执行 RETN 指令返回到 CALL 处的下一行,fun 函数就执行完毕了。

    补充

        本例中并没有演示函数参数在堆栈中的存放规则,只演示了局部变量的。

        实际上,函数参数存放在比 EBP 大的位置,和局部变量存放的地址增长方向恰恰相反。也就是说,如果多定义一个局部变量,ESP 会越来越小于 EBP,它们之间的“空隙”会越来越大,以存放更多的局部变量。但是,如果给函数多增加一个参数,函数调用者的 ESP (也就是被调用者的 EBP)会越来越大于 ESP,“空隙”也将存放更多的参数,因为函数的参数会在调用者去 CALL 被调用者之前被压栈,ESP 将增大,这个 ESP 将成为被调用者的 EBP。最终,我们看到的就是函数中局部变量的地址比 EBP 小,而函数的参数的地址比 EBP 大,它们以 EBP 为界,且地址增长方向相反。

  • 相关阅读:
    TP-LINK,TL-WR885路由器无线桥接方法
    python3 urllib.request.Request的用法
    requests模块
    python3中引入扩展包时的几个注意事项
    Flask-sqlacodegen之ORM操作
    mysql ERROR 1049 (42000): Unknown database '******' ”错误处理办法
    Python各种包下载路径
    python在Apache中的部署
    Python3 基于 Nginx或Apache 部署 Django 项目
    Python如何发布程序
  • 原文地址:https://www.cnblogs.com/yenyuloong/p/9621538.html
Copyright © 2011-2022 走看看