【发布时间】:2015-03-12 09:15:45
【问题描述】:
谁能告诉我这个汇编指令的意义是什么:
0xb48daed9 <+3479>: lea -0xc(%ebp),%esp
我对组装说明不太满意。实际上,我在我的应用程序中得到了一个 SIGABRT,而罪魁祸首似乎是这条特殊的汇编指令。
【问题讨论】:
谁能告诉我这个汇编指令的意义是什么:
0xb48daed9 <+3479>: lea -0xc(%ebp),%esp
我对组装说明不太满意。实际上,我在我的应用程序中得到了一个 SIGABRT,而罪魁祸首似乎是这条特殊的汇编指令。
【问题讨论】:
在机械层面上,指令
lea -0xc(%ebp),%esp
将-0xc(即:-12)添加到%ebp,并将结果写入%esp。
在逻辑层面,它分配被调用函数的栈帧。我希望在与此类似的上下文中看到它:
push %ebp ; save previous base pointer
mov %esp,%ebp ; set %ebp = %esp: old stack pointer is new base pointer
lea -0xc(%ebp),%esp ; allocate 12 bytes for local variables
%ebp 和 %esp 是堆栈指针寄存器。 %ebp 指向堆栈帧的底部,%esp 指向它的“顶部”(实际上是底部,因为堆栈向下增长),因此 lea 指令将堆栈指针移动到底部下方 12 个字节,从而获得声明局部变量的 12 个字节。在保存旧基指针并将新基指针设置为旧堆栈指针后执行此操作会将 12 字节的新帧推入调用堆栈。
这条指令本身似乎不太可能导致陷阱,但在堆栈溢出的情况下,分配的堆栈帧将无效,并且在尝试使用它时会发生爆炸。我怀疑你有一个失控的递归函数。
正如@abligh 提到的,另一种可能性是堆栈指针在沿线某处损坏。如果在堆栈分配的缓冲区中发生缓冲区溢出,从而导致先前保存的基指针被垃圾覆盖,则可能会发生这种情况。从函数返回后,垃圾会被恢复以代替被覆盖的基指针,随后的函数调用将没有任何可处理的东西。
【讨论】:
lea -0xc(%ebp),%esp 将:
%ebp - 12的有效地址[1],并%esp
它已经/被用于对内存操作数执行快速算术运算。根据 Intel 手册,如果源操作数不是内存位置,它可能会抛出异常。
[1]“有效地址”,用 Intel 的说法,是一个偏移量,可以作为静态值或以下形式的地址计算提供:Offset = Base + (Index * Scale) + Displacement
【讨论】:
%esp 等于%ebp-12。 (但我不知道它会抛出异常。)