Aşağıdaki (çok basit) C programının X86_64 üzerinde GDB'de sökülmesini analiz ediyorum.Yığın değişkenlerinin adreslenmesi
int main()
{
int a = 5;
int b = a + 6;
return 0;
}
X86_64'te yığının büyüyeceğini anlıyorum. Bu yığının tepesinin, yığının altından daha düşük bir adresi vardır. aşağıdaki gibi yukarıdaki program çeviricidir:
- Biz yığında baz işaretçi itme:
I anlıyoruz.Dump of assembler code for function main: 0x0000000000400474 <+0>: push %rbp 0x0000000000400475 <+1>: mov %rsp,%rbp 0x0000000000400478 <+4>: movl $0x5,-0x8(%rbp) 0x000000000040047f <+11>: mov -0x8(%rbp),%eax 0x0000000000400482 <+14>: add $0x6,%eax 0x0000000000400485 <+17>: mov %eax,-0x4(%rbp) 0x0000000000400488 <+20>: mov $0x0,%eax 0x000000000040048d <+25>: leaveq 0x000000000040048e <+26>: retq End of assembler dump.
- Ardından yığın işaretçisinin değerini temel işaretçiye kopyalarız.
- Daha sonra 5 değerini
-0x8(%rbp)
adresine kopyalarız. Bir int 4 bayt olduğundan bu-0x8(%rbp)
? Yerine-0x4(%rbp)
olan sonraki adreste olmamalıdır. - Daha sonra
a
değişkenindeki değeri%eax
'a kopyalayın, 6 ekleyin ve sonra değeri-0x4(%rbp)
adresindeki adrese kopyalayın. referans için bu grafiği kullanarak
:
o yığını gibi görünüyor http://eli.thegreenplace.net/images/2011/08/x64_frame_nonleaf.png
içeriği şu şekildedir:
|--------------|
| rbp | <-- %rbp
| 11 | <-- -0x4(%rbp)
| 5 | <-- -0x8(%rbp)
bu bekliyordum:
|--------------|
| rbp | <-- %rbp
| 5 | <-- -0x4(%rbp)
| 11 | <-- -0x8(%rbp)
whi Onlar takımını göstermek nerede ch 7-understanding-c-by-learning-assembly durumda gibi görünüyor:
(gdb) disassemble
Dump of assembler code for function main:
0x0000000100000f50 <main+0>: push %rbp
0x0000000100000f51 <main+1>: mov %rsp,%rbp
0x0000000100000f54 <main+4>: mov $0x0,%eax
0x0000000100000f59 <main+9>: movl $0x0,-0x4(%rbp)
0x0000000100000f60 <main+16>: movl $0x5,-0x8(%rbp)
0x0000000100000f67 <main+23>: mov -0x8(%rbp),%ecx
0x0000000100000f6a <main+26>: add $0x6,%ecx
0x0000000100000f70 <main+32>: mov %ecx,-0xc(%rbp)
0x0000000100000f73 <main+35>: pop %rbp
0x0000000100000f74 <main+36>: retq
End of assembler dump.
a
açıkça beyan ve ilk başlatıldığında
b
değeri
a
daha yığını içinde daha yüksek bir bellek adresi içine konulmaktadır Neden
?
Derleyici, otomatik süre değişkenlerini yığında tamamen hissediyorsa, bir kerede boşta serbesttir. Sadece derleyicilerin en saf hali kod boyunca ilerler ve her bildirimde ve kapsam çıkışında yığın işaretçisini değiştirir ve farklı derleyiciler ve versiyonları farklı kodlar çıkartabilir. C standardının, iki otomatik değişkenin göreli adresleri hakkında söyleyecek hiçbir şeyi yoktur. –