Raspi(armv7l)とM2 MacでアセンブラでHello World

# 背景
[Binary Hacks Rebooted](https://www.oreilly.co.jp/books/9784814400850/)に「アセンブリ言語でのHello World」があり、手元のRaspberry Piで動かしてみましたが、ハマったので記録を残しておきます。

# 内容
[Binary Hacks Rebooted](https://www.oreilly.co.jp/books/9784814400850/)では[x86-64](https://ja.wikipedia.org/wiki/X64)上で動くLinuxを対象に、アセンブリ言語のHello Worldが説明されています。x86-64はintelの64ビットに拡張されたアーキテクチャです。

``` helllo_syscall.asm
section .text
_start:
    mov rdx, 0xe
    mov rsi, msg
    mov rdi, 0x1
    mov rax, 0x1
    syscall
    mov rdi, 0x0
    mov rax, 0x3c
    syscall
section .rodata
    msg: db "Hello, World!", 0xa
```

上記のコードを使って
```
nasm -f elf64 ./hello_syscall.asm
ld -o hello_syscall ./hello_syscall.o
./hello_syscall
```
を実行すれば、Hello Worldできると思ったのですが、
（気づいてみると当たり前のことなんですが）そんなことはなかった。
そもそもx86-64とARMの32bitでアーキテクチャが違う。

今回私が使っているRaspberry Piはarmv7l(ARMの第7世代でLittle Endian)で、32bitアーキテクチャです。
```
uname -a
Linux raspberrypi 5.15.76-v7+ #1597 SMP Fri Nov 4 12:13:17 GMT 2022 armv7l GNU/Linux
```

[NASM](https://ja.wikipedia.org/wiki/Netwide_Assembler)はintel x86を対象としたアセンブラなので、私が使っているARMの32bitの環境では使えないです。

以下、ARMの32bit環境で、intel x86を対象としたアセンブラを使って上手くいかない実行例です。

```
nasm -f elf64 ./hello_syscall.asm
ld -o hello_syscall ./hello_syscall.o
./hello_syscall.o: file not recognized: file format not recognized
```

```
nasm -f elf32 ./hello_syscall.asm
./hello_syscall.asm:3: error: instruction not supported in 32-bit mode
./hello_syscall.asm:4: error: instruction not supported in 32-bit mode
./hello_syscall.asm:5: error: instruction not supported in 32-bit mode
./hello_syscall.asm:6: error: instruction not supported in 32-bit mode
./hello_syscall.asm:8: error: instruction not supported in 32-bit mode
./hello_syscall.asm:9: error: instruction not supported in 32-bit mode
```

[NASM](https://ja.wikipedia.org/wiki/Netwide_Assembler)ではなく、[GNU as](https://ja.wikipedia.org/wiki/GNU%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%A9)を使うのが正しかったです。それに伴ってIntel記法ではなくAT&T記法でhelllo_syscall.asmをhelllo_syscall.sに書き直してあげました。

```helllo_syscall.s
.global _start

.section .text
_start:
    mov r0, #1
    ldr r1, =msg
    mov r2, #14
    mov r7, #4
    svc #0

    mov r7, #1
    mov r0, #0
    svc #0

.section .data
msg:
    .asciz "Hello, world!\n"
```

```
as hello_syscall.s -o hello_syscall.o
gcc -nostartfiles hello_syscall.o -o hello_syscall
./hello_syscall
Hello, world!
```

できました！自分が使ってるアーキテクチャを意識するって大事ですね。
ちなみにM2MacではNASMでHello Worldできました。
アーキテクチャ違うはずなのだけど、データ構造分かれば対応できるのか。

```
nasm -f macho64 hello_syscall_mac.asm 
ld hello_syscall_mac.o -macos_version_min 14.0 -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem
ld: warning: no platform load command found in '/Users/yoheikato/work/asm/hello_syscall_mac.o', assuming: macOS
./a.out 
Hello, World!
```

```hello_syscall_mac.asm 
; Enable relative addressing for position-independent code
default rel

section .text
align 16       ; 16-byte alignment for code section
global _main
_main:
    mov rdx, 0xe              ; message length
    lea rsi, [rel msg]        ; load address using RIP-relative addressing
    mov rdi, 0x1              ; stdout file descriptor
    mov rax, 0x2000004        ; write syscall
    syscall
    mov rdi, 0x0              ; exit code 0
    mov rax, 0x2000001        ; exit syscall
    syscall

section .rodata
align 16                      ; 16-byte alignment for data section
msg:
    db "Hello, World!", 10
    align 8                   ; Ensure alignment after the string
```

ちなみにx86-64の環境を素直に用意しようと思うと、
EC2を用意するのが速いですね。

```
[ec2-user@ip-172-31-1-160 asm]$ nasm -f elf64 ./hello_syscall.asm 
[ec2-user@ip-172-31-1-160 asm]$ ld -o hello_syscall ./hello_syscall.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
[ec2-user@ip-172-31-1-160 asm]$ ls
hello_syscall  hello_syscall.asm  hello_syscall.o
[ec2-user@ip-172-31-1-160 asm]$ ls -l hello_syscall
-rwxr-xr-x. 1 ec2-user ec2-user 8880 Mar  2 08:09 hello_syscall
[ec2-user@ip-172-31-1-160 asm]$ ./hello_syscall 
Hello, World!
```



# 参考文献

* [Binary Hacks Rebooted](https://www.oreilly.co.jp/books/9784814400850/)
* [x86-64](https://ja.wikipedia.org/wiki/X64)
* [NASM](https://ja.wikipedia.org/wiki/Netwide_Assembler)
* [GNU as](https://ja.wikipedia.org/wiki/GNU%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%A9)
* [【x64】アセンブリ読解の基礎知識①](https://qiita.com/mamaru/items/082bb1ebdf845e523eed)
* [X86アセンブラ/GASでの文法](https://ja.wikibooks.org/wiki/X86%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%A9/GAS%E3%81%A7%E3%81%AE%E6%96%87%E6%B3%95)
* [Linuxでx86アセンブラ（道具編）](https://qiita.com/MoriokaReimen/items/b316a68d76c1eafa18f8)
* [Mac でアセンブリを書いてみる](https://qiita.com/dora-gt/items/889a564ebd682fbe4257)