我和几个朋友正在摆弄一个非常奇怪的问题。我们在应用程序内部遇到了一个小的汇编程序部分崩溃(用于加速进程)。错误是由于摆弄堆栈指针而不是最后重置它,它看起来像这样:
push ebp
mov ebp, esp
; do stuff here including sub and add on esp
pop ebp
如果正确,则应写为:
push ebp
mov ebp, esp
; do stuff here including sub and add on esp
mov esp,ebp
pop ebp
现在我们的思维是什么:为什么这在Windows中有效?当我们将应用程序移植到Linux时,我们发现了错误,我们遇到了崩溃。无论是在Windows还是Android(使用NDK),我们都遇到了任何问题,并且永远不会发现此错误。是否有任何Stackpointer恢复?有没有防止滥用stackpointer的保护?
答案 0 :(得分:1)
ebp esp用法,称为堆栈帧,其目的是在堆栈上分配变量,然后在mov esp, ebp
指令之前快速恢复堆栈。所有新版本的x86 CPU都可以使用输入/离开指令将这些指令压缩在一起。
esp是执行push / pop / call / ret时CPU使用的实际堆栈指针。 ebp是一个用户操作的基指针,或多或少所有编译器都将它用作本地存储的堆栈指针。
如果缺少pop ebp
指令,当CPU达到{{1}}时,如果esp!= ebp,则堆栈将出现异常,但仅限于此。
答案 1 :(得分:0)
似乎编译器会在windows中处理你的堆栈:
我能想象的唯一方法是:
Microsoft Visual C特别关注B {__ stdcall}的函数。由于参数数量在编译时是已知的,因此编译器会在符号名称本身中对参数字节计数进行编码
__stdcall约定主要由Windows API使用,它比__cdecl更紧凑。主要的区别在于任何给定的函数都有一组硬编码的参数,并且这在C语言中不能像C语言那样变化(没有“可变函数”)。
见:
http://unixwiz.net/techtips/win32-callconv-asm.html
和:
https://en.wikipedia.org/wiki/X86_calling_conventions