我正在尝试理解堆栈机制。
根据我所看到的理论,在调用函数之前,它的参数被压入堆栈。
但是,在下面的代码中调用printf时,没有一个被推送:
#include<stdio.h>
int main(){
char *s = " test string";
printf("Print this: %s and this %s \n", s, s);
return 1;
}
我在gdb中对printf指令进行了中断,当显示堆栈时,3个参数都没有被压入堆栈。
唯一推送到堆栈的是字符串地址s,如下面的反汇编代码所示:
0x000000000040052c <+0>: push %rbp
0x000000000040052d <+1>: mov %rsp,%rbp
0x0000000000400530 <+4>: sub $0x10,%rsp
0x0000000000400534 <+8>: movq $0x400604,-0x8(%rbp) // variable pushed on the stack
0x000000000040053c <+16>: mov -0x8(%rbp),%rdx
0x0000000000400540 <+20>: mov -0x8(%rbp),%rax
0x0000000000400544 <+24>: mov %rax,%rsi
0x0000000000400547 <+27>: mov $0x400611,%edi
0x000000000040054c <+32>: mov $0x0,%eax
0x0000000000400551 <+37>: callq 0x400410 <printf@plt>
0x0000000000400556 <+42>: mov $0x1,%eax
0x000000000040055b <+47>: leaveq
实际上,到目前为止在反汇编代码中出现的唯一一个论点是“打印这个:%s和这个%s \ n”放在%edi ...
0x0000000000400547 <+27>: mov $0x400611,%edi
所以我的问题是:为什么我的三个论点中没有看到3个推送说明?
uname -a: 3.8.0-31-generic#46-Ubuntu SMP Tue Sep 10 20:03:44 UTC 2013 x86_64 x86_64 x86_64 GNU / Linux
答案 0 :(得分:3)
在64位Linux x86-64系统上,x86-64 ABI(x86-64 Application Binary Interface)不会在堆栈上推送参数,而是使用一些寄存器(此calling convention稍快一点)
如果您传递了许多参数-e.g.其中一些人被推到了堆栈上。
在阅读x86-64 ABI规范之前,或许先阅读x86 calling conventions上的wikipage。
对于像printf
这样的可变函数,细节有点可怕。
答案 1 :(得分:-1)
根据您的编译器,您需要在堆上为指针'分配空间。
代替
char *s;
使用
char s[300];
分配300字节的房间
否则's'只是指向堆栈 - 可以是随机的
这可能是您没有看到PUSH指令的部分原因。
另外,我不明白为什么printf中需要指针的PUSH指令?汇编程序只是复制(MOV)指针的值