【发布时间】:2019-12-28 02:58:12
【问题描述】:
我使用https://godbolt.org/ 和“x86-64 gcc 9.1”来汇编以下 C 代码,以了解为什么将指向局部变量的指针作为函数参数传递是有效的。现在我很难理解一些步骤。
我评论了我遇到困难的台词。
void printStr(char* cpStr) {
printf("str: %s", cpStr);
}
int main(void) {
char str[] = "abc";
printStr(str);
return 0;
}
.LC0:
.string "str: %s"
printStr:
push rbp
mov rbp, rsp
sub rsp, 16 ; why allocate 16 bytes when using it just for the pointer to str[0] which is 4 bytes long?
mov QWORD PTR [rbp-8], rdi ; why copy rdi to the stack...
mov rax, QWORD PTR [rbp-8] ; ... just to copy it into rax again? Also rax seems to already contain the pointer to str[0] (see *)
mov rsi, rax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
nop
leave
ret
main:
push rbp
mov rbp, rsp
sub rsp, 16 ; why allocate 16 bytes when "abc" is just 4 bytes long?
mov DWORD PTR [rbp-4], 6513249
lea rax, [rbp-4] ; pointer to str[0] copied into rax (*)
mov rdi, rax ; why copy the pointer to str[0] to rdi?
call printStr
mov eax, 0
leave
ret
【问题讨论】:
-
16 个字节用于对齐。您正在查看未优化的代码,看到废话不要感到惊讶。将
-O3添加到编译器选项。rdi用于按照standard calling convention 传递第一个参数。 -
@Jester 谢谢。这就是我的答案。
-
一般来说,未优化代码的编译方式使得它在调试器中单步执行时表现良好
-
可能是 Why does clang produce inefficient asm with -O0 (for this simple floating point sum)? 的副本,这解释了为什么
-O0会这样做。