概要
- 最初に学んだプログラミング言語は ActionScript、高水準なWeb系言語への興味
- 低水準言語やマシンコードへの苦手意識を克服し、実際はそれほど難しくないと気付く
- マシンコードには 命令セット ごとの違いがあり、ARM(aarch64)とx86-64が代表的
- 基本概念は 命令・レジスタ・メモリ の3つ
- 低水準の知識習得は、プログラミング全体の理解を深める鍵
マシンコードへの苦手意識と克服
- ActionScript からプログラミングを始めた経緯
- 高水準な Web言語 への興味、低水準言語への苦手意識
- マシンコード(機械語)は難解だという先入観
- Google検索 でも学習よりも否定的な情報が多い現状
- 目標達成のため、苦手意識を乗り越える必要性を痛感
マシンコードの本質と基礎
- マシンコードは 怖くない、基本を押さえれば理解可能
- JSONスキーマに従ったJSONを作れるなら、マシンコードも書ける
- 命令セット の多様性(x86-64、ARM、その他アーキテクチャ)
- 本記事の目的は、特定命令セットの深掘りではなく、マシンコード一般の理解促進
- 例として ARM 64bit(aarch64) を中心に解説、後半でx86-64にも触れる
マシンコードの3要素
- 命令 :実行する処理内容(加算、移動、減算、ジャンプなど)
- レジスタ :値を一時的に保存する場所、変数のような役割
- メモリ :データの格納場所、リストや配列のイメージ
ARM命令の構造
- 例:加算命令(add immediate)のビット構成
- 各ビットは命令の要素や値を表現
- sf :64bit/32bitレジスタの指定
- sh :シフト指定、imm12と連携して大きな数値を表現
- imm12 :12ビット即値(定数)
- Rn/Rd :ソース・デスティネーションレジスタ指定
- 命令は データ構造 として捉えられる
レジスタの役割
- ARM(AArch64)では X0~X30 の31個の汎用レジスタ
- レジスタ番号は 5ビット で表現
- 呼び出し規約(Calling Convention)による役割分担
- 実際のコーディングでは アセンブリ記法 を利用
- 例:add x1, x0, #0x2a(42を加算)
メモリ操作命令
- 例: STR(store)命令 でレジスタの値をメモリに保存
- メモリアドレス+オフセットに値を書き込む
- xビットで64bit/32bit指定
- アセンブリ記法例:str x2, [x1, #0x2]
x86-64命令の特徴
- 命令・レジスタ・メモリ の基本構造は同じ
- レジスタ名は rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, r8~r15
- x86は 可変長命令、32bit固定ではない
- 命令構成要素
- REXプレフィックス :64bit操作やレジスタ拡張
- ModR/M :レジスタ/メモリ指定
- OpCode :操作内容を表す数値
- 例:REX.W + C7 /0 id(32bit即値を64bitレジスタへ)
まとめと学習のすすめ
- 低水準の知識は プログラミング理解の底上げ に不可欠
- ライブラリ依存からの脱却、根本理解の深化
- ドキュメントや解説の分かりにくさが障壁の主因
- Compiler Explorer などのツールで実際に試すことの重要性
- 低水準が苦手な人ほど、基礎から学ぶ価値