这些无用的流水线从何而来? [复制]
Posted
技术标签:
【中文标题】这些无用的流水线从何而来? [复制]【英文标题】:Where are these useless Assembly lines come from? [duplicate] 【发布时间】:2020-05-23 23:20:05 【问题描述】:我开始学习汇编,所以我使用命令gcc -S file.c
来获取我的 C 代码的汇编版本。
一切正常,但我注意到当我输入一个简单的代码时,例如:
void ft_return_strlen(char *str)
int a;
a = strlen(str);
return (a);
gcc -S file.c
命令给了我这个:
_ft_return_strlen:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rdi
callq _ft_strlen
movl %eax, -12(%rbp)
movl -12(%rbp), %eax
addq $16, %rsp
popq %rbp
retq
即使这个函数没用,为什么 gcc 给我这些行?
movq %rdi, -8(%rbp)
movq -8(%rbp), %rdi
他们不是没用吗?如果这些行真的没用,它们是来自我的代码还是来自 gcc?有什么办法可以改善吗?
【问题讨论】:
尝试优化:gcc -O3
它们不是没用的,它们的存在是有原因的,但它与优化级别有关,尝试 -O2 或赌博 -O3
确实你是对的,当我使用优化时它们会消失。我将阅读有关此优化标志的更多信息。谢谢!
【参考方案1】:
未优化,编译器为变量str分配空间,即-8(%rbp)
。顶部的所有代码都是在寄存器 rbp 和 rsp 之间为局部变量在堆栈上腾出一个空间。
函数调用将它放在寄存器 rdi 中,但调试器需要在名为 str 的变量中看到它。如果在调试器中您要更改变量 str,则需要将该新值作为参数复制回 strlen。
同样的情况发生在变量 a,-12(%rbp)
,它必须从返回寄存器 rax 复制,然后复制回来以返回,以防你在调试器中编辑它。
通过优化,变量被完全丢弃,但调试器知道等价物在寄存器中。在最大优化下,整个函数可以被删除,或者用 jmp 替换为 strlen,但是你根本无法调试它!
【讨论】:
但调试器知道等价物在寄存器中不幸的是,您通常会得到“优化”,而不是编译器打印一个存在于寄存器中的变量。至少在带有 GDB 的 GNU/Linux 上。 @PeterCordes 是的,它在调试器中的价值有限,因为寄存器经常被重用,但我发现它偶尔会给出答案。 如果你正在查看 asm,当然你可以自己print $rdi
,但我通常发现当一个 var 被优化为寄存器时,GDB 根本不知道去哪里看.可能在大多数情况下,C var 已被优化并被 GCC 发明的临时替代。 (如果您使用 -fverbose-asm
查看 GCC asm 输出,您会看到类似 D.1234
的名称)。我曾假设调试信息格式可能甚至无法指示 C 变量在寄存器中,但可能不是这种情况。以上是关于这些无用的流水线从何而来? [复制]的主要内容,如果未能解决你的问题,请参考以下文章