所以我正在尝试编写一些x86来为结构分配内存.我的c代码看起来像这样......
struc *uno = malloc(sizeof(struc));
uno->first = 0;
uno->second = 0;
uno->third = 0;
//And the struct
struct struc {
int first;
int second;
int *third;
}
Run Code Online (Sandbox Code Playgroud)
拆卸看起来像......
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $12, (%esp)
call malloc
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
movl $0, (%eax)
movl -12(%ebp), %eax
movl $0, 4(%eax)
movl -12(%ebp), %eax
movl $0, 8(%eax)
movl $0, %eax
Run Code Online (Sandbox Code Playgroud)
所以我有几个问题......
1)结构的大小是16,但为什么程序集只显示它分配12?
2)这是什么意思
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
Run Code Online (Sandbox Code Playgroud)
是不是只是将eax的内容放入ebp-12的地址中.那么第二个语句是多余的?
3)当没有其他局部变量或参数被推入堆栈时,为什么esp会减少40?我以为它只需要递减16.
任何帮助表示赞赏,以及我认为您认为相关的任何内容.我对装配很新.谢谢.
结构的大小为12.两个整数和指针在x86上都是4个字节,因此没有填充,结构的大小为12. sizeof如果不确定类型的大小,可以随时询问编译器.
您正在编译而没有优化,因此代码似乎效率低下.
movl $12, (%esp)
call malloc
movl %eax, -12(%ebp)
Run Code Online (Sandbox Code Playgroud)
这会调用malloc,然后将返回的值保存%eax到uno存储在的局部变量中-12(%ebp).因此,这三个指令组成了调用malloc:准备堆栈,调用函数,保存返回值.
我们继续下一行.
uno->first = 0;
Run Code Online (Sandbox Code Playgroud)
因为没有优化,编译器没有意识到%eax已经包含了值,uno因此它再次加载它,然后将零写入第一个成员
movl -12(%ebp), %eax
movl $0, (%eax)
Run Code Online (Sandbox Code Playgroud)
接下来是
uno->second = 0;
Run Code Online (Sandbox Code Playgroud)
我们再次加载unointo 的值%eax,并将此值写入零,这次是偏移量为4的第二个成员
movl -12(%ebp), %eax
movl $0, 4(%eax)
Run Code Online (Sandbox Code Playgroud)
你明白了,我确信我不需要解释最后的任务.
尝试使用优化进行编译,输出看起来会非常不同.编译器应该能够优化uno到%eax堆栈中而不是将它放在堆栈上.它可以产生这个代码:
movl $12, (%esp)
call malloc
movl $0, (%eax)
movl $0, 4(%eax)
movl $0, 8(%eax)
Run Code Online (Sandbox Code Playgroud)
我不确定为什么你认为堆栈保留应该是16个字节.malloc在上面的优化变体中,我只看到需要4个字节,传递给的参数.如果没有优化,我猜测是8,参数是4,局部变量是4.但我不知道为什么函数为堆栈保留40个字节.也许答案可以在其中一个问题中找到:
最后,查看优化代码可能会更有效率.如果没有优化,编译器可能会采取许多看似奇怪的决策 优化后代码将更加简洁,从长远来看,您为真实执行的代码可能已经过优化.