【问题标题】:Printf arguments not pushed on the stackPrintf 参数未压入堆栈
【发布时间】:2013-10-21 12:00:08
【问题描述】:

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

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

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

【问题讨论】:

    标签: c assembly gdb stack push


    【解决方案1】:

    在 64 位 Linux x86-64 系统上,x86-64 ABI (x86-64 Application Binary Interface) 不会将参数推送到堆栈上,而是使用一些寄存器(这个 calling convention 稍微快一些)。

    如果你传递了很多参数 -e.g.十几个 - 其中一些被推入堆栈。

    也许在阅读 x86-64 ABI 规范之前先阅读x86 calling conventions 上的维基页面。

    对于像printf 这样的可变参数函数,细节有点吓人。

    【讨论】:

      【解决方案2】:

      根据您的编译器,您需要在堆上为指针“s”分配空间。 代替 char *s; 采用 char s[300]; 分配 300 字节的空间 否则 's' 只是指向堆栈 - 可以是随机的

      这可能是您看不到 PUSH 指令的部分原因。

      另外,我不明白为什么 printf 中需要的指针应该有一个 PUSH 指令?汇编器只是简单地复制(MOV)指针的值

      【讨论】:

      • 不,如何传递参数是 ABI 的问题。声明一个 300 字节的本地字符串只会影响第一条指令(设置调用框架),而不影响参数的传递方式。
      • 是的,你是对的 Basile。我应该更多地关注 printf 函数的编译器 (ABI)。
      猜你喜欢
      • 2013-12-26
      • 1970-01-01
      • 2013-10-12
      • 2012-04-27
      • 2015-01-03
      • 2012-09-26
      • 2014-02-14
      • 2014-04-16
      • 1970-01-01
      相关资源
      最近更新 更多