带有 x64 工作站的 GCC

Posted

技术标签:

【中文标题】带有 x64 工作站的 GCC【英文标题】:GCC with x64 sta 【发布时间】:2013-01-07 16:31:00 【问题描述】:

谁能向我解释为什么下面的代码行 int main (int argc, char *argv[])


int i=17;
int output=0

.....


翻译成以下 x64 汇编代码:

pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
movl %edi, -20(%rbp)
movq %rsi,-32(%rbp)
movl $17, -8(%rbp)
movl $0, -4(%rbp)
...

我不明白为什么 SP 减少了 32。寄存器 %edi、%rsi 似乎对应于主代码中未使用的 argc 和 *argv[]。我认为 [%esp, %rbp] 之间的空间仅分配给局部变量而不是函数 args,因此在上面的代码中大小应该只有 8,即 rsp 应该减少 8 而不是 32。请解释一下?

【问题讨论】:

参考forum.valhallalegends.com/index.php?topic=16602.0 msdn.microsoft.com/en-us/magazine/cc301698.aspx 看来都是编译器优化的部分。但是,由于它仍然需要遵守调用约定(在本例中为 cdecl),因此它们在被调用后仍然存储在堆栈中。 对我来说,看起来 GCC 像这样布置堆栈:[输出:4 字节] - [i:4 字节] - [对齐填充:12 字节] - [home EDI 的空间: 4 字节] - [到家 RSI 的空间:8 字节]。我猜这 12 个填充字节是为了将堆栈重新对齐到 16 字节边界。 【参考方案1】:

了解 ... 部分会有所帮助。

我假设 gcc 决定 ... 部分需要寄存器,因此它将变量推入堆栈。

堆栈可用于任何局部变量或函数参数。 SysV x64 ABI 的唯一要求是前几个函数参数以寄存器开头。

然后该函数可以将参数移到堆栈上,并根据需要将局部变量带入寄存器,这取决于编译器!

不保证将本地变量放入堆栈! args 也不会留在寄存器中。

所以它推动了 argc 和 argv,然后它决定推动 i 和输出。那是 24 字节的空间。但如果接下来是函数调用,则堆栈必须对齐到 16 个字节,因此达到 32 个字节。

试试 -O3 看看代码是否有变化。

换一种说法:

Args 是这样的: %rdi %rsi %rdx %rcx %rbx %r8 %r9 (堆栈上的额外参数) (红色区域)

是函数的开始。然后该函数可以对堆栈做任何它想做的事情。是的,随便!只要它以它进入的状态返回堆栈。

(注意,这是针对系统 V(除 windows 外的所有设备都使用),windows 不同)

【讨论】:

以上是关于带有 x64 工作站的 GCC的主要内容,如果未能解决你的问题,请参考以下文章

如何搭建基于gcc和eclipse的x64开发环境?

你如何建立一个基于gcc和eclipse的x64开发环境?

让 ScriptControl 与 Excel 2010 x64 一起工作

centos6 x64下编译gcc-4.8.5

ODBC x64 oracle 问题

尝试下载 EXE 文件后,PowerShell (x64) 停止工作 (Windows 7)