2017-05-30 58 views
0

我目前正在讀的書黑客:開發的由Jon埃裏克森藝術。我通過這本書,努力迫使我研究的機器,32位和64個系統之間的差異,以加強我的理解提供了一個64位的Ubuntu 16.04.2系統上的練習,而不是虛擬機一起以下。我現在正朝着本書的開始,學習堆棧框架組裝,但是我對在機器上運行這些結果感到困惑。當使用GCC編譯代碼:堆棧框架組件 - 緩衝器/垃圾空間和堆棧上的參數位置 - Ubuntu的64

void test_function(int a, int b, int c, int d) { 
    int flag; 
    char buffer[10]; 

    flag = 31337; 
    buffer[0] = 'A'; 
} 

int main() { 
    test_function(1, 2, 3, 4); 
} 

我給大會:

Dump of assembler code for function main: 
    0x000000000040058b <+0>:  push rbp 
    0x000000000040058c <+1>:  mov rbp,rsp 
    0x000000000040058f <+4>:  mov ecx,0x4 
    0x0000000000400594 <+9>:  mov edx,0x3 
    0x0000000000400599 <+14>: mov esi,0x2 
    0x000000000040059e <+19>: mov edi,0x1 
    0x00000000004005a3 <+24>: call 0x400546 <test_function> 
    0x00000000004005a8 <+29>: mov eax,0x0 
    0x00000000004005ad <+34>: pop rbp 
    0x00000000004005ae <+35>: ret 

Dump of assembler code for function test_function: 
    0x0000000000400546 <+0>:  push rbp 
    0x0000000000400547 <+1>:  mov rbp,rsp 
    0x000000000040054a <+4>:  sub rsp,0x40 
    0x000000000040054e <+8>:  mov DWORD PTR [rbp-0x34],edi 
    0x0000000000400551 <+11>: mov DWORD PTR [rbp-0x38],esi 
    0x0000000000400554 <+14>: mov DWORD PTR [rbp-0x3c],edx 
    0x0000000000400557 <+17>: mov DWORD PTR [rbp-0x40],ecx 
    0x000000000040055a <+20>: mov rax,QWORD PTR fs:0x28 
    0x0000000000400563 <+29>: mov QWORD PTR [rbp-0x8],rax 
    0x0000000000400567 <+33>: xor eax,eax 
    0x0000000000400569 <+35>: mov DWORD PTR [rbp-0x24],0x7a69 
    0x0000000000400570 <+42>: mov BYTE PTR [rbp-0x20],0x41 
    0x0000000000400574 <+46>: nop 
    0x0000000000400575 <+47>: mov rax,QWORD PTR [rbp-0x8] 
    0x0000000000400579 <+51>: xor rax,QWORD PTR fs:0x28 
    0x0000000000400582 <+60>: je  0x400589 <test_function+67> 
    0x0000000000400584 <+62>: call 0x400420 <[email protected]> 
    0x0000000000400589 <+67>: leave 
    0x000000000040058a <+68>: ret 

使用GDB設置在test_function一個破發點,我看存儲器,以查看方式堆棧幀被修建了。

(gdb) x/20hw $rsp 
0x7fffffffddd0: 0x00000004 0x00000003 0x00000002 0x00000001 
0x7fffffffdde0: 0x00000001 0x00000000 0x004005fd 0x00000000 
0x7fffffffddf0: 0x00000000 0x00000000 0x00000000 0x00000000 
0x7fffffffde00: 0x004005b0 0x00000000 0x00400450 0x00000000 
0x7fffffffde10: 0xffffde20 0x00007fff 0x004005a8 0x00000000 

而且寄存器設置爲:

(gdb) i r rip rsp rbp 
rip   0x40055a 0x40055a <test_function+20> 
rsp   0x7fffffffddd0 0x7fffffffddd0 
rbp   0x7fffffffde10 0x7fffffffde10 

我的問題是,爲什麼是參數通過0x7fffffffdddf位於內存地址0x7fffffffddd0的功能,而保存的幀指針是在0x7fffffffde10和返回地址是0x7fffffffde18。我會認爲這些值將被存儲在內存中,但由於某些原因,編譯器會將參數存儲在64位的位置。

起初我以爲這可能是一個對齊問題,以及自由空間可能是緩衝空間,但是從我在網上搜集,記憶往往在16個間隔排列,而不是64位。如果內存以16位間隔對齊,那麼爲什麼不將參數存儲在0x7fffffffde00到0x7fffffffde0f?

此外,不返回地址和參數之間的空間有任何意義,或者這僅僅是垃圾數據?在0x7fffffffdde8,0x7fffffffde00和0x7fffffffde08的價值觀似乎對他們似乎是在記憶的文本段的內存地址是有點有趣,但也有可能,這是在棧的常用段分配緩衝空間的結果。

+2

所以編譯器不會嘗試做任何明智的。它只是把事情放在自己方便的地方。 –

回答

0

你很可能看到了「紅番區」。

https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r252.pdf

https://stackoverflow.com/tags/x86/info標籤wiki有很多偉大的鏈接。

這談論你不優化編譯上的紅色區域https://softwareengineering.stackexchange.com/questions/230089/what-is-the-purpose-of-red-zone

+0

我也意識到我正在定義test_function中的一些變量,它將佔據大部分可用空間。 – user2985955

+1

該代碼未使用紅色區域。堆棧中的所有東西都在堆棧指針之上。 –