我反汇编了一个像strlen一样工作的函数:
有人能解释一下如何对我有用吗?我知道它用于获取字符串的长度,我想知道的是它是如何做到的。
另外,有一件事让我对汇编感到困惑的是如何将变量存储在堆栈中。它们是按声明顺序(var _8,var _4,arg_0)还是最后一个存储的?它们是以新月形式还是以渐弱的方式存储在ebp中(参考它们存储的地址)? 我读到它们可以以一种新的方式存储,因为ebp具有更高的值地址并且被称为C约定,然后是Pascal约定,这是另一种方式...我怎么知道哪个程序正在使用?如果您能在解释中解决这些问题,我将不胜感激。
感谢。
答案 0 :(得分:1)
这是一个非常糟糕的汇编语言片段 它使用stack frame中的局部变量,即使它有足够的寄存器。
如您所见,它使用cdecl
calling convention,因为它的单个参数是使用堆栈传输的。
该函数只接受一个参数:[arg_0]
:指向zero terminated string的指针
它有两个局部变量[var_4]
:字符串的长度计数器和[var_8]
:字符串中运行pointer。
中间块一次读取一个字节的字符串并测试该字节是否为零。如果是这样我们就完成了并且可以返回长度 如果不是,我们以极其低效的方式增加字符串指针并增加长度计数器并跳回中间块以测试下一个字节。
esp sub esp,8
操作为局部变量创建空间称为堆栈帧,Pascal和C(如果优化已关闭)都将生成堆栈帧。
但是,Pascal调用约定传递寄存器中的前3个参数(eax,edx,ecx)。 C使用cdecl
调用约定来推送堆栈上的所有参数。
完成后,将长度加载到eax
(所有调用约定中的函数始终在eax
中返回结果。)
它清理了堆栈框架:mov esp,ebp; pop ebp
之后,它使用近似返回来返回调用者:retn
您可以区分局部变量和参数,因为局部变量与ebp
具有负偏移,并且参数与ebp
具有正偏移。
如果您忘记启用优化,则会获得此类代码 永远不要看未经优化的汇编代码,它教会你不良习惯,并且会混淆而不是启发你。