从汇编代码到C代码
这是AT&T的语法从汇编代码到C代码,c,assembly,att,C,Assembly,Att,这是AT&T的语法 .global bar .type bar, @function bar: pushl %ebp movl %esp, %ebp pushl %ebx subl $20, %esp movl 8($ebp), %ebx movl $1, %eax cmpl $1, %ebx jle .L3 leal -1(%ebx), %eax //subtracts 1 from ebx and stores into eax movl %eax, (%esp) //putti
.global bar
.type bar, @function
bar:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
movl 8($ebp), %ebx
movl $1, %eax
cmpl $1, %ebx
jle .L3
leal -1(%ebx), %eax //subtracts 1 from ebx and stores into eax
movl %eax, (%esp) //putting on stack frame
call bar //recursive call
addl %ebx, %eax // adds %ebx and %eax
.L3 //returns %eax
addl $20, %esp
popl %ebx
popl %ebp
ret //end of bar
所以我认为这里发生的基本上是它检查%ebx是否是intbar(intx)
{
如果(x我会这样注释它:
bar: // bar() {
pushl %ebp // function prologue
movl %esp, %ebp //
pushl %ebx //
subl $20, %esp //
movl 8($ebp), %ebx // %ebx = x
movl $1, %eax // %eax = 1
cmpl $1, %ebx // if (x > 1)
jle .L3 // {
leal -1(%ebx), %eax // %eax = x - 1
movl %eax, (%esp) // put (x - 1) on stack
call bar // %eax = bar(x - 1)
addl %ebx, %eax // %eax += x
.L3 // }
addl $20, %esp // function epilogue
popl %ebx //
popl %ebp //
ret // return %eax
// }
因此,C看起来与您发布的内容相当:
int bar (int x)
{
if (x > 1)
return bar(x - 1) + x;
return 1;
}
出于历史兴趣:我使用clang-m32-S
编译了您的原始(不正确)C代码,在手动稍微“优化”以消除存储/加载对之后,我得到了类似于您的汇编代码的东西,但很明显您当时错了。您从那时起就修复了它。我不知道您从哪里得到了x+(x-1)
用于递归调用参数。调用后有一个add
,您似乎混淆了调用前发生的事情。leal-1(%ebx),%eax
是一个有效加载的地址指令。它在x86手册中有记录(大部分在线)。它用于存储带偏移量的地址,但有时它用于通过一次移动和常量添加来保存一条指令。我不知道在堆栈上添加eax
的位置。你必须将其移动到堆栈,这是将其作为参数传递给bar
@潜伏者所必需的。我意识到我是这样做的我放弃了对它的递归调用,正在对它进行回溯。leal命令从ebx中减去1,并将其存储到eax中,虽然正确吗?是的,这是正确的。@潜伏者我重新查看了它,并再次尝试解决方案。我认为它实际上只是将值从x相加到1。我将简化推送%ebp/mov%上的注释esp,%ebp
到//堆栈帧样板文件
“调用堆栈”甚至不完全准确,因为它是在推送之后完成的。而且,“展开”意味着(对我来说)按照堆栈帧的链接列表将调用链备份到某个父函数的堆栈帧。我会说“将堆栈指针还原到我们保存寄存器的位置”之类的东西。@PeterCordes:很公平——我现在用“序言”和“尾声”替换了这些注释,我认为这是非常标准的。是的,我喜欢它。它不是函数逻辑的一部分,只是为ABI实现它的一部分(使用一些保留调用的寄存器和通常的堆栈帧约定)。这不是跟踪实际逻辑以查看函数的功能时需要关注的内容。
bar: // bar() {
pushl %ebp // function prologue
movl %esp, %ebp //
pushl %ebx //
subl $20, %esp //
movl 8($ebp), %ebx // %ebx = x
movl $1, %eax // %eax = 1
cmpl $1, %ebx // if (x > 1)
jle .L3 // {
leal -1(%ebx), %eax // %eax = x - 1
movl %eax, (%esp) // put (x - 1) on stack
call bar // %eax = bar(x - 1)
addl %ebx, %eax // %eax += x
.L3 // }
addl $20, %esp // function epilogue
popl %ebx //
popl %ebp //
ret // return %eax
// }
int bar (int x)
{
if (x > 1)
return bar(x - 1) + x;
return 1;
}