【发布时间】:2015-01-20 15:19:15
【问题描述】:
我现在正在学习汇编,但我对(大概)标准函数模板一无所知。
因此,基于this really nice book,“函数要记住的形式如下:”
function_label:
pushl %ebp
movl %esp, %ebp
< normal function code goes here>
movl %ebp, %esp
popl %ebp
ret
好的,我很好,但是有一件小事我不明白。在“正常功能代码”之后,我们恢复esp 的初始(调用前)值,该值之前存储在ebp 中。
现在,我清楚地理解了为什么我们要将 esp 值原封不动地返回给调用上下文。我不明白的是在什么条件下esp 值可以在函数执行期间完全改变。
此模板中是否包含某种针对我们自己的保护(以防我们以某种方式破坏了代码中某处的堆栈)?或者也许改变函数内部的堆栈值是一种正常的做法?
或者即使我们不做任何事情,初始的esp 值也可能在执行过程中最终改变? (事实上,我无法弄清楚这是怎么回事。)
想到这个我觉得很傻,并在这个简单的代码中用gdb检查了esp的值:
.section .data
message:
.asciz "> Hello from function #%d\n"
.section .text
.globl main
main:
nop
call overhere
pushl $0
call exit
overhere:
pushl %ebp
movl %esp, %ebp
pushl $1
pushl $message
call printf
add $8, %esp
movl %ebp, %esp
popl %ebp
ret
而esp(正如我实际预期的那样)没有受到影响,因此将ebp 移动到esp 实际上并没有改变任何东西。
现在,我希望我想知道什么很清楚:
-
esp的值最终会自行改变吗? (我敢打赌它不能。) - 如果不能,那么上面的这个模板显然假定程序员可能会在函数内部以某种方式更改它。但我不明白为什么在地球上可能需要这样做,所以 - 更改
esp值是一个错误吗?
提前谢谢你,原谅我的无知。
【问题讨论】:
标签: function assembly x86 stack gnu-assembler