機械語
CPU が直接実行できるビット列。
01001000 10001001 11011000これが x86-64 の mov %rbx, %rax にあたる。
命令の構造#
おおむね次の要素からなる。
| 部分 | 内容 |
|---|---|
| オペコード | 何をするか(加算、移動、分岐) |
| オペランド | どのレジスタ、どのアドレス |
| 即値 | 定数 |
命令長#
| ISA | 命令長 |
|---|---|
| x86-64 | 1〜15 バイト(可変) |
| ARM64 | 4 バイト固定 |
| RISC-V | 4 バイト(圧縮拡張で 2 バイトも) |
可変長はコード密度が高い代わりに、 デコードが難しい。 命令の切れ目を知るには前から順に解釈するしかなく、 並列デコードの障害になる。 これが x86 の実装が複雑になる主因のひとつ。
データとの区別がつかない#
メモリ上では、機械語もデータも同じビット列。 「ここから実行する」と決めたら命令として解釈される。
これがフォン・ノイマン型の柔軟さの源であり、 同時にバッファオーバーフローによる任意コード実行の 根本原因でもある。
対策として NX ビット(実行不可のページ)、 ASLR(配置のランダム化)などが導入されている。
逆アセンブル#
機械語からアセンブリに戻すこと。 可変長命令では、開始位置がずれると まったく別の命令列に見えるため、 完全に正しく戻すのは一般には難しい。
参考文献#
- Randal E. Bryant, David R. O’Hallaron. Computer Systems: A Programmer’s Perspective, 3rd ed. Pearson, 2016. https://csapp.cs.cmu.edu/
- Intel 64 and IA-32 Architectures Software Developer Manuals. https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
- Tool Interface Standard (TIS). Executable and Linking Format (ELF) Specification, v1.2. https://refspecs.linuxfoundation.org/elf/elf.pdf