Printf参数没有被压在堆栈上

时间:2013-10-13 23:20:04

标签: c assembly gdb stack push

我正在尝试理解堆栈机制。

根据我所看到的理论,在调用函数之前,它的参数被压入堆栈。

但是,在下面的代码中调用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

2 个答案:

答案 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)指针的值