2013-10-13 74 views
2

我正在嘗試理解堆棧機制的過程。Printf參數沒有壓入堆棧

根據我所看到的理論,在函數被調用之前,它的參數被壓入堆棧。

然而,在下面的代碼中調用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 <[email protected]> 
    0x0000000000400556 <+42>: mov $0x1,%eax 
    0x000000000040055b <+47>: leaveq 

其實,在反彙編代碼到目前爲止出現的唯一參數是在「打印:%s和該%S \ n」被放在%EDI ...

0x0000000000400547 <+27>: mov $0x400611,%edi 

所以我的問題是:爲什麼我沒有看到我的每個三個參數3個推指示?

UNAME -a: 3.8.0-31泛型#46-Ubuntu的SMP星期二09月10 20點03分44秒UTC 2013 x86_64的x86_64的x86_64的GNU/Linux的

回答

3

在64位的Linux x86-64系統,x86-64 ABI(x86-64 Application Binary Interface)不會在堆棧上推送參數,但會使用一些寄存器(此calling convention稍快)。

如果你通過許多論據 - 例如,一打 - 他們中的一些被推入堆棧。

也許在閱讀x86-64 ABI規範之前先閱讀x86 calling conventions上的wikipage。

對於像printf這樣的可變參數的細節有點嚇人。

-1

根據你的編譯器,你將需要在堆上爲你的指針分配空間。 而不是 char *s; 使用 char s[300]; 分配300個字節的 否則「S」簡直是朝上書庫 - 它可以是隨機

這可能是部分原因,您沒有看到PUSH指令。

此外,我不明白爲什麼應該有printf所需的指針的PUSH指令?彙編器只是複製(MOV)指針的值

+0

不,這是ABI如何傳遞參數的問題。聲明一個300字節的本地字符串只會影響第一條指令(設置調用幀),而不會影響參數傳遞的方式。 –

+0

是的,你是對的巴西爾。我應該更多地關注printf函數的編譯器(ABI)。 – Grantly