【问题标题】:gcc, start symbol and push $0x00gcc,开始符号并推送 $0x00
【发布时间】:2012-06-19 23:25:31
【问题描述】:

所以我已经搜索了几个星期的互联网,但找不到我的问题的答案。

我可以看到 gcc 添加的开始符号设置了最初的两个参数(int argc,char *argv[]),我相信第三个环境参数,但我对此有几个问题。如果 main() 函数被定义为没有参数,为什么还要添加所有这些?如果它只调用 _main 而没有任何参数,它不会节省空间(和技术上的处理时间)吗? 其次 push $0x0 是做什么的?我已经完成了测试,如果您尝试像默认开始符号那样迭代命令行参数,那么您需要在开头 push $0x0,否则如果我执行以下操作会产生未对齐的堆栈错误:

push $0x00
call _main
mov %eax, %edi
call _exit

在我的调查中,我还发现当您链接到 crt1.10.6.o 时,链接器会添加起始符号

任何解释或文档将不胜感激

【问题讨论】:

    标签: gcc assembly


    【解决方案1】:

    如您所见,_start 的代码来自名为 crt1.o 或类似名称的目标文件。该目标文件通常来自作为 C 库一部分的源代码。它是在不知道您如何声明main 函数的情况下编译的,因此它必须假定您希望使用所有三个潜在 参数。即使main 不使用它们,设置参数也没有坏处(正如你提到的,除了微不足道的空间和时间)。

    我从mov %eax,%edi推断这是x86-64 ELF ABI,这意味着没有帧指针,所以push $0x00确实只是为了保持堆栈与16字节边界对齐,因为你推测。 (在 x86-32 ELF ABI 中,它也可以作为帧指针链表的终止符。)

    【讨论】:

    • 谢谢!你的推论(不确定这是否是正确的语法)是正确的。
    • nw 我的下一个问题是为什么堆栈需要对齐到 16 字节边界?
    • 这允许编译器将变量 within 堆栈帧对齐到 16 字节边界,这可以使事情更快地工作。
    • 所以如果你要压入 0x0 然后从堆栈指针中减去 16 它/wouldnt/崩溃?我觉得我完全误解了这个边界的东西编辑:所以我只是用谷歌搜索了“16 字节边界”,现在我理解了一半的性能,但我仍然不明白为什么这与push $0x00 有关 - 它是否强制堆栈一个 16 字节的边界?那么你怎么能从堆栈中只减去 8 呢?你不会至少需要减去 16 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多