#include <stdio.h>
static int i = 100;
/* Declard as extern since defined in hello.c */
extern int global;
int function(char *input)
{
printf("%s\n", input);
return global;
};
.file "foo.c"
.data
.align 4
.type i, @object
.size i, 4
i:
.long 100
.text
.globl function
.type function, @function
function:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call puts
movl global, %eax
leave
ret
.size function, .-function
.ident "GCC: (Debian 4.4.5-8) 4.4.5"
.section .note.GNU-stack,"",@progbits
原因是什么:
subl $ 24,%esp
为什么他通过将stackpointer减少24个字节来在堆栈上为局部变量创建空间?函数中没有局部变量。 然后他做了:
movl%eax,(%esp)
为什么 - 因为存储在ebp + 8中的值(指针字符*输入)被移动到eax 现在应该传递给puts ..但是为什么他会做先前的subl - 存储int的返回值?但那是4个字节。我也读过C的确如此 不支持调用函数必须在堆栈上腾出空间 返回值(renetrancy问题)。请问这里发生了什么:( ??他可以 将指针参数对齐在单词边界上..但是接着是SysV I386 ABI说使用了尾部填充物。
此外,
movl%esp,%ebp
暗示esp和ebp都指向新函数堆栈的基础 帧。但是,假设有一个“呼叫功能”;考虑堆栈: 你有:
pushl ptr //push char *ptr call function { pushl ebp So stack contains: ptr ret-value ebp ->with-esp-pointing-to-after-ebp (ESP always points to the top of the stack but after the last pushed element..?)
所以他将ebp设置为esp。但是在pg36的ABI规范中,SysV ABI I386架构处理器补充4E,他说: 0(%ebp)之前的%ebp(可选) 我猜的是:%ebp + 0指向前一个ebp 但正如你所看到的,ebp + 0实际指向存储的前一个ebp之后.. ???
也在另一个程序中,
andl $-16, %esp subl $32, %esp
所以他首先记下esp的最后4位...嗯这是多少空间 给他?然后是subl ..
有人可以建议一个体面的教程或书籍..我不想 主汇编,只是想了解一点ABI规范和对齐以及GOT / PLT /虚拟寻址和编译器/链接器 stuff-symbolTable / relocation等(我正在使用Levine的书,但它很大 - 虽然很有趣但是COFF和IBM / Sparc的东西:(这就是我开始的原因) ABI规范。还有Ian Wienand的网站:来自的计算机科学 自下而上。)