目的
リトルエンディアンのメモリの並びを見る。
x86とARMでメモリの配置を比べます。
ずっとARMはビックエンディアンしかないと思い込んでおり、x86とARMで逆になっているという記事を書きたかったのですが、ARM両方で動作できるみたいで、筆者の使っているARM小型サーバではリトルエンディアンとなっていたのでビックエンディアンの検証はできませんでした。
前回以下の記事を書きましたが、内容的にはこれらを合わせて、構成を見直して読みやすくしただけです。
ARM32上でC言語のローカル変数がスタックにどう配置されるかを観察する
Cのローカル変数はメモリ上でどう配置されるか? – x86-64 スタックと RBP オフセットの観察
C言語
void func(){
volatile int a = 0x12345678;
volatile char b = 0xAB;
}
int main(){
func();
return 0;
}
x86
逆アセンブルして各命令のアドレスを調べる。
gcc -no-pie -gstabs -O0 test.c -o test
objdump -d -M intel test
0000000000401106 <func>:
401106: f3 0f 1e fa endbr64
40110a: 55 push rbp
40110b: 48 89 e5 mov rbp,rsp
40110e: c7 45 fc 78 56 34 12 mov DWORD PTR [rbp-0x4],0x12345678
401115: c6 45 fb ab mov BYTE PTR [rbp-0x5],0xab
401119: 90 nop
40111a: 5d pop rbp
40111b: c3 ret
nop命令で実行を止めてメモリの配置を確認する
gdb test
break *0x401119 # nopにブレイクポイントを置く
run # nopを実行する直前まで動かす。
info registers rbp # rbpの値を確認する
x/8xb $rbp-0x8
実際に値を確認
test@test-ThinkPad-X280:~/test$ gdb test
(gdb) break *0x401119
Breakpoint 1 at 0x401119: file test.c, line 4.
(gdb) run
Starting program: /home/test/test/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, func () at test.c:4
4 }
(gdb) info registers rbp
rbp 0x7fffffffdfd0 0x7fffffffdfd0
(gdb) x/8xb $rbp-0x8
0x7fffffffdfc8: 0x64 0x00 0x00 0xab 0x78 0x56 0x34 0x12
メモリの分布は以下の様になっている。
0x7fffffffdfc8: 0x64
0x7fffffffdfc9: 0x00
0x7fffffffdfca: 0x00
0x7fffffffdfcb: 0xab
0x7fffffffdfcc: 0x78 ← 変数a終了
0x7fffffffdfcd: 0x56
0x7fffffffdfce: 0x34
0x7fffffffdfcf: 0x12 ← 変数a開始
ARM32
実験に使うLinux小型サーバがリトルエンディアンかビットエンディアンか調べる。
testuser@CasaOS:~/test$ lscpu | grep Endian
Byte Order: Little Endian
逆アセンブルして各命令のアドレスを調べる。
gcc -no-pie -g -O0 test.c -o test
objdump -d test
実際に値を確認
000103c0 <func>:
103c0: b480 push {r7}
103c2: b083 sub sp, #12
103c4: af00 add r7, sp, #0
103c6: f245 6378 movw r3, #22136 @ 0x5678
103ca: f2c1 2334 movt r3, #4660 @ 0x1234
103ce: 607b str r3, [r7, #4]
103d0: 23ab movs r3, #171 @ 0xab
103d2: 70fb strb r3, [r7, #3]
103d4: bf00 nop
103d6: 370c adds r7, #12
103d8: 46bd mov sp, r7
103da: f85d 7b04 ldr.w r7, [sp], #4
103de: 4770 bx lr
nop命令で実行を止めてメモリの配置を確認する
gdb ./test
break *0x103d4
run
info registers r7
x/8xb $r7
testuser@CasaOS:~/test$ gdb ./test
(gdb) break *0x103d4
Breakpoint 1 at 0x103d4: file test.c, line 4.
(gdb) run
Starting program: /home/testuser/test/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
Breakpoint 1, func () at test.c:4
4 }
(gdb) info registers r7
r7 0xbefff3d8 3204445144
(gdb) x/8xb $r7
0xbefff3d8: 0x90 0x41 0xec 0xab 0x78 0x56 0x34 0x12
メモリの分布は以下の様になっている。
0xbefff3d8: 0x90
0xbefff3d9: 0x41
0xbefff3da: 0xec
0xbefff3db: 0xab
0xbefff3dc: 0x78 ← 変数a終了
0xbefff3dd: 0x56
0xbefff3de: 0x34
0xbefff3df: 0x12 ← 変数a開始
リトルエンディアンなのでx86と同じく高アドレスに上位ビット、低アドレスに下位ビットの順番で並んでいる。
動作環境(Linux / x86_64 版)
OS: Ubuntu 22.04.5 LTS (Jammy Jellyfish)
Kernel: Linux 6.8.0-84-generic
CPU: Intel Core i5-8250U, 4 cores, 8 threads, Little Endian
Architecture: x86_64
動作環境(Linux / ARM 版)
OS: Armbian 23.08.0-trunk (Debian 12 Bookworm)
Kernel: Linux 6.1.38-meson (armv7l)
CPU: ARM Cortex-A5, 4 cores, Little Endian
Architecture: armv7l
備考: UbuntuからSSH接続して使用