現在のブログ
ゲーム開発ブログ (2025年~) Gamedev Blog (2025~)
レガシーブログ
テクノロジーブログ (2018~2024年) リリースノート (2023~2025年) MeatBSD (2024年)
【マシン言語】マシン言語でプログラミングする方法
去年はアセンブリ言語について沢山取り上げました。
アセンブリ言語でプログラミングする事で、プログラミングの容易さと移植性を犠牲にして、パフォーマンスを最適化し、コンパイラの排除します。
然し、其れよりも更に一段階低いレベルはどうでしょうか?
アセンブラとリンカも排除出来るとしたら?
マシン言語の登場です。
デモシーン、組み込み系の低レベル開発者、リバースエンジニア、そして死ぬまで待てない人々以外は、直接マシン言語を書く人は殆どいません。
然し、マシンがコードをどの様に理解するかを知っておくのは良い事ですし、自分でアセンブラやリンカを作りたい人にとっても非常に役立ちます。
此の実験では、AArch64機(具体的にはラスパイ5)上のLinuxを使用します。
$ farfetch
___ suwako@crux-rpi5
(.· | ------------------
(<> | OS: Linux 6.12.25-v8-16k+ aarch64
/ __ \ Distro: CRUX-ARM64
( / \ /| Host: Raspberry Pi 5 Model B Rev 1.1
_/\ __)/_) Uptime: 0 days, 46 mins
\/-____\/ Shell: zsh 5.9
CPU: @ GHz (4 core)
Memory: 175 MiB / 8059 MiB
Storage: /dev/root: 13G / 113G
オペコード
先ずオペコードを知る必要があります。
去年すでに説明した様に、アセンブリ言語は単に人間が読み易い形式のマシンコードです。
従って、AArch64アセンブリ言語を知っているなら、技術的にはAArch64マシンコードも知っている事になります。
此れらがオペコードです:
mov → D280
adr → 1000
svc → D400
コード
D2 80 0B A8
D2 80 05 40
D4 00 00 01
此れは以下と同等です:
mov x8, #93
mov x0, #42
svc #0
然し、此れだけでは未だ不十分です。
実際に実行する為には、先ず適切なヘッダが必要です。
7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
02 00 b7 00 01 00 00 00 78 00 40 00 00 00 00 00
40 00 00 00 00 00 00 00 a0 02 00 00 00 00 00 00
00 00 00 00 40 00 38 00 01 00 40 00 06 00 05 00
01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00
00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00
b5 00 00 00 00 00 00 00 b5 00 00 00 00 00 00 00
00 00 01 00 00 00 00 00 08 08 80 d2 20 00 80 d2
c1 00 00 10 a2 03 80 d2 01 00 00 d4 a8 0b 80 d2
40 05 80 d2 01 00 00 d4 e3 81 93 e3 82 93 e3 81
ab e3 81 a1 e3 81 af e3 80 81 e4 b8 96 e7 95 8c
ef bc 81 0a 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 03 00 01 00 78 00 40 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 03 00 02 00
98 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 04 00 f1 ff 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 08 00 00 00 00 00 02 00
98 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
0c 00 00 00 00 00 f1 ff 1d 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 13 00 00 00 00 00 01 00
78 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
25 00 00 00 10 00 02 00 b5 00 41 00 00 00 00 00
00 00 00 00 00 00 00 00 16 00 00 00 10 00 02 00
b5 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00
24 00 00 00 10 00 02 00 b5 00 41 00 00 00 00 00
00 00 00 00 00 00 00 00 35 00 00 00 10 00 01 00
78 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
30 00 00 00 10 00 02 00 b5 00 41 00 00 00 00 00
00 00 00 00 00 00 00 00 3c 00 00 00 10 00 02 00
b8 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00
44 00 00 00 10 00 02 00 b5 00 41 00 00 00 00 00
00 00 00 00 00 00 00 00 4b 00 00 00 10 00 02 00
b8 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00
00 6d 61 69 6e 2e 6f 00 6d 73 67 00 6d 73 67 4c
65 6e 00 24 78 00 5f 5f 62 73 73 5f 73 74 61 72
74 5f 5f 00 5f 5f 62 73 73 5f 65 6e 64 5f 5f 00
5f 5f 62 73 73 5f 73 74 61 72 74 00 5f 5f 65 6e
64 5f 5f 00 5f 65 64 61 74 61 00 5f 65 6e 64 00
00 2e 73 79 6d 74 61 62 00 2e 73 74 72 74 61 62
00 2e 73 68 73 74 72 74 61 62 00 2e 74 65 78 74
00 2e 72 6f 64 61 74 61 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1b 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00
78 00 40 00 00 00 00 00 78 00 00 00 00 00 00 00
20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
21 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00
98 00 40 00 00 00 00 00 98 00 00 00 00 00 00 00
1d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 b8 00 00 00 00 00 00 00
68 01 00 00 00 00 00 00 04 00 00 00 07 00 00 00
08 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00
09 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 20 02 00 00 00 00 00 00
50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 70 02 00 00 00 00 00 00
29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16進エディタがない場合は、次の様に出来ます:
$ cat > elf.hex << 'EOF'
7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
02 00 b7 00 01 00 00 00 78 00 40 00 00 00 00 00
40 00 00 00 00 00 00 00 a0 02 00 00 00 00 00 00
00 00 00 00 40 00 38 00 01 00 40 00 06 00 05 00
01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00
00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00
b5 00 00 00 00 00 00 00 b5 00 00 00 00 00 00 00
00 00 01 00 00 00 00 00 08 08 80 d2 20 00 80 d2
c1 00 00 10 a2 03 80 d2 01 00 00 d4 a8 0b 80 d2
40 05 80 d2 01 00 00 d4 e3 81 93 e3 82 93 e3 81
ab e3 81 a1 e3 81 af e3 80 81 e4 b8 96 e7 95 8c
ef bc 81 0a 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 03 00 01 00 78 00 40 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 03 00 02 00
98 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 04 00 f1 ff 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 08 00 00 00 00 00 02 00
98 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
0c 00 00 00 00 00 f1 ff 1d 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 13 00 00 00 00 00 01 00
78 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
25 00 00 00 10 00 02 00 b5 00 41 00 00 00 00 00
00 00 00 00 00 00 00 00 16 00 00 00 10 00 02 00
b5 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00
24 00 00 00 10 00 02 00 b5 00 41 00 00 00 00 00
00 00 00 00 00 00 00 00 35 00 00 00 10 00 01 00
78 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
30 00 00 00 10 00 02 00 b5 00 41 00 00 00 00 00
00 00 00 00 00 00 00 00 3c 00 00 00 10 00 02 00
b8 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00
44 00 00 00 10 00 02 00 b5 00 41 00 00 00 00 00
00 00 00 00 00 00 00 00 4b 00 00 00 10 00 02 00
b8 00 41 00 00 00 00 00 00 00 00 00 00 00 00 00
00 6d 61 69 6e 2e 6f 00 6d 73 67 00 6d 73 67 4c
65 6e 00 24 78 00 5f 5f 62 73 73 5f 73 74 61 72
74 5f 5f 00 5f 5f 62 73 73 5f 65 6e 64 5f 5f 00
5f 5f 62 73 73 5f 73 74 61 72 74 00 5f 5f 65 6e
64 5f 5f 00 5f 65 64 61 74 61 00 5f 65 6e 64 00
00 2e 73 79 6d 74 61 62 00 2e 73 74 72 74 61 62
00 2e 73 68 73 74 72 74 61 62 00 2e 74 65 78 74
00 2e 72 6f 64 61 74 61 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1b 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00
78 00 40 00 00 00 00 00 78 00 00 00 00 00 00 00
20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
21 00 00 00 01 00 00 00 02 00 00 00 00 00 00 00
98 00 40 00 00 00 00 00 98 00 00 00 00 00 00 00
1d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 b8 00 00 00 00 00 00 00
68 01 00 00 00 00 00 00 04 00 00 00 07 00 00 00
08 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00
09 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 20 02 00 00 00 00 00 00
50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 70 02 00 00 00 00 00 00
29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
EOF
$ xxd -r -p elf.hex > exe
$ chmod +x exe
$ ./exe
こんにちは、世界!
スペースと改行は削除しても構いませんが、内部でxxdが全て除去するので違いはありません。
スペースと改行があると読み易く成ります。
次にバイナリを検査出来ます。
$ ls -thal exe
-rwxr-xr-x 1 suwako wheel 1008 5月 6 20:43 exe
$ file exe
exe: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, missing section headers at 992
$ readelf -h exe
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: AArch64
Version: 0x1
Entry point address: 0x400078
Start of program headers: 64 (bytes into file)
Start of section headers: 672 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 1
Size of section headers: 64 (bytes)
Number of section headers: 6
Section header string table index: 5
readelf: Error: Reading 384 bytes extends past end of file for section headers
$ readelf -l exe
readelf -l exe
readelf: Error: Reading 384 bytes extends past end of file for section headers
Elf file type is EXEC (Executable file)
Entry point 0x400078
There is 1 program header, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000000b5 0x00000000000000b5 R E 0x10000
僅か1008バイト!
アセンブリ言語で書いた同じプログラム(1.1 KiB)と比べて少しだけ小さく成りました。
欠点はバイナリが100%有効な形式ではない事ですが、動作します。
利点は、パディングを全て削除する事でバイナリを更に小さく出来る事です。
最後の00を削除すると993バイトに成ります。
何処まで小さく出来るか試してみましょう。
7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
02 00 b7 00 01 00 00 00 78 00 40 00 00 00 00 00
40 00 00 00 00 00 00 00 a0 02 00 00 00 00 00 00
00 00 00 00 40 00 38 00 01 00 40 00 06 00 05 00
01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00
00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00
b5 00 00 00 00 00 00 00 b5 00 00 00 00 00 00 00
00 00 01 00 00 00 00 00 08 08 80 d2 20 00 80 d2
c1 00 00 10 a2 03 80 d2 01 00 00 d4 a8 0b 80 d2
40 05 80 d2 01 00 00 d4 e3 81 93 e3 82 93 e3 81
ab e3 81 a1 e3 81 af e3 80 81 e4 b8 96 e7 95 8c
ef bc 81 0a 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 03 00 01 00 78 00 40 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 03 00 02 00
98 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 04 00 f1 ff 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 08 00 00 00 00 00 02 00
98 00 40 0c 00 00 00 00 00 f1 ff 1d 13 00 00 00
00 00 01 00 78 00 40 25 00 00 00 10 00 02 00 b5
00 41 16 00 00 00 10 00 02 00 b5 00 41 24 00 00
00 10 00 02 00 b5 00 41 35 00 00 00 10 00 01 00
78 00 40 30 00 00 00 10 00 02 00 b5 00 41 3c 00
00 00 10 00 02 00 b8 00 41 44 00 00 00 10 00 02
00 b5 00 41 4b b8 00 41 00 6d 61 69 6e 2e 6f 00
6d 73 67 00 6d 73 67 4c 65 6e 00 24 78 00 5f 5f
62 73 73 5f 73 74 61 72 74 5f 5f 00 5f 5f 62 73
73 5f 65 6e 64 5f 5f 00 5f 5f 62 73 73 5f 73 74
61 72 74 00 5f 5f 65 6e 64 5f 5f 00 5f 65 64 61
74 61 00 5f 65 6e 64 00 00 2e 73 79 6d 74 61 62
00 2e 73 74 72 74 61 62 00 2e 73 68 73 74 72 74
61 62 00 2e 74 65 78 74 00 2e 72 6f 64 61 74 61
1b 01 06 78 40 78 20 04 21 01 02 98 40 98 1d 01
01 02 b8 68 01 04 07 08 18 09 20 02 50 01 11 00
00 00 03 70 02 29 01
$ xxd -r -p elf.hex > exe
$ ./exe
こんにちは、世界!
$ ls -thal exe
-rwxr-xr-x 1 suwako wheel 551 5月 6 20:59 exe
既に551バイトまで小さく成りました。
もっと小さく出来るはずです。
7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
02 00 b7 00 01 00 00 00 78 00 40 00 00 00 00 00
40 00 00 00 00 00 00 00 a0 02 00 00 00 00 00 00
00 00 00 00 40 00 38 00 01 00 40 00 06 00 05 00
01 00 00 00 05 00 00 00 00 00 00 00 00 00 00 00
00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00
b5 00 00 00 00 00 00 00 b5 00 00 00 00 00 00 00
00 00 01 00 00 00 00 00 08 08 80 d2 20 00 80 d2
c1 00 00 10 a2 03 80 d2 01 00 00 d4 a8 0b 80 d2
40 05 80 d2 01 00 00 d4 e3 81 93 e3 82 93 e3 81
ab e3 81 a1 e3 81 af e3 80 81 e4 b8 96 e7 95 8c
ef bc 81 0a 03 01 78 40 03 02 98 40 01 04 f1 ff
08 02 40 0c f1 ff 1d 13 01 78 40 25 10 02 b5 41
16 10 02 b5 41 24 10 02 b5 41 35 10 01 78 40 30
10 02 b5 41 3c 10 02 b8 41 44 10 02 b5 41 4b b8
41 6d 61 69 6e 2e 6f 6d 73 67 6d 73 67 4c 65 6e
24 78 5f 5f 62 73 73 5f 73 74 61 72 74 5f 5f 5f
5f 62 73 73 5f 65 6e 64 5f 5f 5f 5f 62 73 73 5f
73 74 61 72 74 5f 5f 65 6e 64 5f 5f 5f 65 64 61
74 61 5f 65 6e 64 2e 73 79 6d 74 61 62 2e 73 74
72 74 61 62 2e 73 68 73 74 72 74 61 62 2e 74 65
78 74 2e 72 6f 64 61 74 61 1b 01 06 78 40 78 20
04 21 01 02 98 40 98 1d 01 01 02 b8 68 01 04 07
08 18 09 20 02 50 01 11 03 70 02 29 01
$ xxd -r -p elf.hex > exe
$ ls -thal exe
-rwxr-xr-x 1 suwako wheel 381 5月 6 21:15 exe
$ file exe
exe: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, missing section headers at 992
$ ./exe
こんにちは、世界!
今381バイトに成りました。
然し、更に小さく出来るでしょうか?
答えは「ノー」です。
此れ以上パディングを減らすとエラーが発生します。
例えば、最初の3.6行(38 00 01 00 40まで)の00を削除するとexe format errorに成ります。
3.6行目から6行目までの00を削除するとsegmentation faultに成ります。
其れ以外の00を削除するとillegal hardware instructionに成ります。
従って、此れが最終結果です。
バイナリをstripすると379バイトに成りますが、文字列が破損し、illegal hardware instructionエラーが続く様に成るので、stripせずに残します。
アセンブリ言語との比較:
.section .rodata
.align 4
msg:
.asciz "こんにちは、世界!\n"
.equ msgLen, .-msg
.section .text
.align 4
.global _start
_start:
mov x8, #64
mov x0, #1
adr x1, msg
mov x2, msgLen
svc #0
mov x8, #93
mov x0, #0
svc #0
$ as main.s -o main.o
$ ld main.o -o main
$ ls -thal main
-rwxr-xr-x 1 suwako wheel 1.1K 5月 6 21:34 main
$ file main
main: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, not stripped
$ strip main
$ ls -thal main
-rwxr-xr-x 1 suwako wheel 472 5月 6 21:35 main
$ file main
main: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped
$ ./main
こんにちは、世界!
マシン言語では381バイト、アセンブリ言語では472バイトに成りました。
C言語はどうでしょうか?
#include <stdio.h>
int main() {
printf("こんにちは、世界!\n");
return 0;
}
$ cc --std=c23 main.c -o mainc -static
$ ls -thal mainc
-rwxr-xr-x 1 suwako wheel 616K 5月 6 21:39 mainc
$ file mainc
mainc: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=c707cb647eedd3367b1e48859a084a0f81052388, for GNU/Linux 3.7.0, not stripped
$ strip mainc
$ ls -thal mainc
-rwxr-xr-x 1 suwako wheel 520K 5月 6 21:39 mainc
$ file mainc
mainc: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=c707cb647eedd3367b1e48859a084a0f81052388, for GNU/Linux 3.7.0, stripped
$ ./mainc
こんにちは、世界!
C言語では520 KiBと大幅に大きく成りました。
C99とC23の両方でコンパイルしましたが、2つの間に全く違いはありませんでした。
C++はどうでしょうか?
C++ではC++11とC++23の両方をテストします。
C++23でようやくテキスト出力のより合理的な方法が導入されました。
#include <iostream>
int main() {
std::cout << "こんにちは、世界!" << std::endl;
return 0;
}
#include <print>
int main() {
std::print("こんにちは、世界!");
return 0;
}
$ c++ --std=c++23 main11.cc -o maincpp11 -static
$ c++ --std=c++23 main23.cc -o maincpp23 -static
$ ls -thal maincpp11
-rwxr-xr-x 1 suwako wheel 2.2M 5月 6 21:44 maincpp11
$ ls -thal maincpp23
-rwxr-xr-x 1 suwako wheel 2.3M 5月 6 21:45 maincpp23
$ file maincpp11
maincpp11: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=48babdac130393529983d36cda30135899a3292b, for GNU/Linux 3.7.0, not stripped
$ file maincpp23
maincpp23: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=501c8926799fae121faeddbba6b33e3732bb83e1, for GNU/Linux 3.7.0, not stripped
$ strip maincpp11
$ strip maincpp23
$ ls -thal maincpp11
-rwxr-xr-x 1 suwako wheel 1.6M 5月 6 21:45 maincpp11
$ ls -thal maincpp23
-rwxr-xr-x 1 suwako wheel 1.7M 5月 6 21:45 maincpp23
$ file maincpp11
maincpp11: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=48babdac130393529983d36cda30135899a3292b, for GNU/Linux 3.7.0, stripped
$ file maincpp23
maincpp23: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=501c8926799fae121faeddbba6b33e3732bb83e1, for GNU/Linux 3.7.0, stripped
$ ./maincpp11
こんにちは、世界!
$ ./maincpp23
こんにちは、世界!
予想通り、此れまででC++が最も大きく成りました。
C++99でもコンパイルを試しましたが、結果はC++11と同じでした。
唯一の違いはコンパイル時間が大幅に速かった事です。
比較として:
$ time c++ --std=c++98 main11.cc -o maincpp99 -static
c++ --std=c++98 main11.cc -o maincpp99 -static 0.41s user 0.06s system 99% cpu 0.464 total
$ time c++ --std=c++03 main11.cc -o maincpp03 -static
c++ --std=c++03 main11.cc -o maincpp03 -static 0.38s user 0.05s system 99% cpu 0.434 total
$ time c++ --std=c++11 main11.cc -o maincpp11 -static
c++ --std=c++11 main11.cc -o maincpp11 -static 0.56s user 0.08s system 99% cpu 0.647 total
$ time c++ --std=c++14 main11.cc -o maincpp14 -static
c++ --std=c++14 main11.cc -o maincpp14 -static 0.62s user 0.07s system 99% cpu 0.692 total
$ time c++ --std=c++17 main11.cc -o maincpp17 -static
c++ --std=c++17 main11.cc -o maincpp17 -static 0.73s user 0.05s system 99% cpu 0.781 total
$ time c++ --std=c++20 main11.cc -o maincpp20 -static
c++ --std=c++20 main11.cc -o maincpp20 -static 0.81s user 0.07s system 99% cpu 0.891 total
$ time c++ --std=c++23 main11.cc -o maincpp23 -static
c++ --std=c++23 main11.cc -o maincpp23 -static 1.72s user 0.11s system 99% cpu 1.822 total
$ time c++ --std=c++26 main11.cc -o maincpp26 -static
c++ --std=c++26 main11.cc -o maincpp26 -static 1.78s user 0.11s system 99% cpu 1.903 total
$ time c++ --std=c++23 main23.cc -o maincpp23 -static
c++ --std=c++23 main23.cc -o maincpp23 -static 2.47s user 0.12s system 99% cpu 2.590 total
$ time c++ --std=c++26 main23.cc -o maincpp26 -static
c++ --std=c++26 main23.cc -o maincpp26 -static 2.70s user 0.08s system 99% cpu 2.780 total
ご覧の通り、C++03のみが古い標準と比べてコンパイルが速い事例です。
又、新しいstd::printはstd::coutに比べて大幅なオーバーヘッドを追加する様です。
おまけとしてZigも試してみましょう。
const std = @import("std");
pub fn main() void {
std.debug.print("こんにちは、世界!\n", .{});
}
$ zig build-exe mainzig.zig -OReleaseSmall -fstrip -dead_strip
$ ls -thal mainzig
-rwxr-xr-x 1 suwako wheel 97K 5月 6 21:54 mainzig
$ file mainzig
mainzig: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped
$ ./mainzig
こんにちは、世界!
以下の様なランキングに成りました:
- マシン言語:381バイト
- アセンブリ言語:472バイト
- Zig言語:97 KiB
- C言語:520 KiB
- C++(
std::coutを利用する場合):1.6 MiB - C++(
std::printを利用する場合):1.7 MiB
以上