個人的に確認したいことがあって、ついでにメモとしてまとめておきます。
struct_sample.c
#includeint main(){ struct person { int age; char *name; }; struct person p1; p1.age = 20; p1.name = "chashu"; return 0; }
$ gcc -g -m32 -o struct_sample struct_sample.c
$ objdump -S struct_test
objdumpのオプションは-dが一般的かもしれないですが-Sを指定するとアセンブリの中にコードも表示してくれます
intel記法が好みなら-M intelで指定できます。
080483db: #include int main(){ 80483db: 55 push %ebp 80483dc: 89 e5 mov %esp,%ebp 80483de: 83 ec 10 sub $0x10,%esp int age; char *name; }; struct person p1; p1.age = 20; 80483e1: c7 45 f8 14 00 00 00 movl $0x14,-0x8(%ebp) p1.name = "chashu"; 80483e8: c7 45 fc 80 84 04 08 movl $0x8048480,-0x4(%ebp) return 0; 80483ef: b8 00 00 00 00 mov $0x0,%eax } 80483f4: c9 leave 80483f5: c3 ret
main関数部分です。
80483de: 83 ec 10 sub $0x10,%esp
スタックを0x10バイト確保しています。int(4バイト)、charポインタ(4バイト)なので計算が合いませんが多分余分に確保しているのでしょう。
p1.age = 20; 80483e1: c7 45 f8 14 00 00 00 movl $0x14,-0x8(%ebp) p1.name = "chashu"; 80483e8: c7 45 fc 80 84 04 08 movl $0x8048480,-0x4(%ebp)
$ebp-0x8にp1.age, $ebp-0x4にp1.nameが配置されてますね。構造体に定義されている順番通りにメモリの低位アドレスから配置されます。
続いてgdbでp1.age = 20;をした直後のp1.ageがあるメモリを確認して見ます。
gdb-peda$ x/4b $ebp-0x8 0xffffcfe0: 0x14 0x00 0x00 0x00
表示されている4バイトがp1.ageです。本来は0x00000014なのに1バイトを1かたまりとして逆順になっています。リトルエンディアンというやつです。
$ebp-0x8のようなアドレスがオペランドとして指定された時は、そのアドレスにある値から4バイト先のアドレスまでの値を取得して、逆順に並べて解釈するという処理がされています。
今回は何バイト先まで取得するかはオペコード次第です。
まとめ
・構造体のメンバは定義されている順番通りにメモリの低位アドレスから配置される。
・各メンバの値はリトルエンディアンで配置されている。(もちろんプロセッサに依存します)