【问题标题】:How assembly accesses/stores variables on the stack程序集如何访问/存储堆栈上的变量
【发布时间】:2014-04-01 05:38:41
【问题描述】:

在汇编中您可以将数据存储在寄存器或堆栈中。在任何给定时刻只能访问堆栈的顶部(对吗?)。考虑以下 C 代码:

main(){
    int x=2;
    func();
}

func( int x ){
    int i;
    char a;
}

在调用 func() 时,以下内容被压入堆栈(考虑 32 位系统):

variable x (4 bytes, pushed by main)
<RETURN ADDRESS> (4 bytes pushed by main?)
<BASE POINTER> (4 bytes pushed by func())
variable i (4 bytes, pushed by func())
variable a (1 byte, pushed by func())

我有以下问题:

  1. 在 C 代码中,您可以从函数内部的任何位置访问局部变量,但在汇编中您只能访问堆栈顶部。 C 代码被翻译成汇编(在机器代码中,但汇编是它的可读形式)。那么汇编如何支持读取不在栈顶的变量呢?

  2. 在我的示例中,我是否遗漏了也将被推送到堆栈的任何内容?

  3. 在汇编中,如果你在堆栈上压入一个char或一个int,它如何确定它需要压入4个字节还是1个字节?因为它使用相同的操作(推)吧?

提前致谢 格。马里克鲁兹

【问题讨论】:

    标签: c assembly stack


    【解决方案1】:

    将函数开头的堆栈指针放入寄存器,然后通过这个基地址加上变量的偏移量来访问变量/参数。

    如果您想查看代码,而不是创建目标文件,让编译器停止创建汇编程序文件。然后你可以确切地看到它是如何工作的。 (当然,这要求你有一个有效的 C 程序,这与你现在的问题不同。)

    【讨论】:

    • 谢谢!是否也可以在某处看到堆栈的当前内容?有什么工具吗?
    • @Maricruzz 任何体面的调试器都应该具有该功能。
    【解决方案2】:

    编译器正在生成程序集,每个指令集可能不同,但归根结底,堆栈只是一个保存内存地址的寄存器。编译器正在创建并且知道它正在创建的函数的整个范围,并且知道在堆栈上找到本地数据项的每个数据项的深度,因此它将基于该指令集创建适当的代码以访问那些本地数据项项目。

    一些指令集需要复制堆栈指针和/或使用堆栈指针作为操作数进行数学运算,但作为该数学运算的结果其他一些寄存器,然后基于该数学运算(堆栈指针 + 8 个字例如)您访问该内存地址。某些指令集具有寻址模式,您可以在加载或存储时对堆栈指针应用偏移量,数学是作为指令执行的一部分完成的,您不必使用中间结果和寄存器。

    【讨论】:

      【解决方案3】:

      在任何给定时刻只能访问堆栈的顶部(对吗?)

      不,通常 ISA 也有访问堆栈上其他元素的指令。即访问栈上的元素不限于pushpop之类的操作;通常你可以在堆栈位置和寄存器之间来回mov

      【讨论】:

        【解决方案4】:

        Assembly 可以通过地址访问任何内存(就像C)。

        简单的,未优化的程序会在方法执行之前将所有局部变量放入堆栈,因此变量地址是执行帧的地址加上一些移位。

        然后程序可以简单地使用poppush 方法将附加变量(即某些表达式的子结果)存储在堆栈顶部。

        总结:

        1. 有寄存器(x86 中的ESP)指向栈顶
        2. 调用push 将变量移动到堆栈顶部并增加此寄存器
        3. 调用pop 是从栈顶移动变量并减少这个寄存器
        4. 调用 mov 是在内存和寄存器之间移动变量,对堆栈寄存器 (ESP) 没有任何作用。

        【讨论】:

        • push 按操作数的大小递减 esp,将操作数存储在 [esp]。 pop 从 [esp] 加载操作数,然后将 esp 增加操作数的大小。禁用“帧指针”后,C 生成的代码使用 esp 的偏移量来定位变量。启用“帧指针”后,函数会执行 push esp | mov ebp,esp,并基于 ebp 的大多数偏移量。
        猜你喜欢
        • 2012-10-19
        • 2015-03-09
        • 2014-12-23
        • 2013-12-31
        • 1970-01-01
        • 1970-01-01
        • 2013-04-02
        • 1970-01-01
        • 2014-04-21
        相关资源
        最近更新 更多