我目前正在讀的書黑客:開發的由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的價值觀似乎對他們似乎是在記憶的文本段的內存地址是有點有趣,但也有可能,這是在棧的常用段分配緩衝空間的結果。
所以編譯器不會嘗試做任何明智的。它只是把事情放在自己方便的地方。 –