assembly-x86 について
assembly-x86は、x86-64アセンブリをエージェントに案内するスキルです。コンパイラ出力の読み解きから、ABI、インラインアセンブリ、SIMD intrinsic まで扱います。
主な機能
- 01コンパイラ生成アセンブリの読解
- 02レジスタと System V ABI の理解
- 03AT&T 構文と Intel 構文の比較
- 04GCC 拡張インラインアセンブリの記述
- 05SSE と AVX intrinsic の使用
- 06一般的な命令パターンの把握
活用シーン
- 01C プログラムの GCC 出力を調べる
- 02関数の引数と戻り値を理解する
- 03C でインラインアセンブリを記述する
- 04一括した値に SIMD 演算を適用する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill assembly-x86インストール後、Claude Code で/assembly-x86を入力して読み込まれたか確認します。
同梱ファイルreferences/reference.md
詳細
x86-64 アセンブリ
目的
コンパイラーの出力の読み方、ABI の理解、インラインアセンブリの記述、一般的なパターンについて、エージェントをガイドします。
トリガー
- 「GCC が生成したアセンブリはどのように読めばよいですか?」
- 「x86-64 のレジスターには何がありますか?」
- 「Linux/macOS の呼び出し規約は何ですか?」
- 「C でインラインアセンブリを書くにはどうすればよいですか?」
- 「SSE/AVX のイントリンシックはどう使えばよいですか?」
- 「このアセンブリには
%rsp/%rbpが使われていますが、どういう意味ですか?」
ワークフロー
1. アセンブリを生成して読む
# AT&T syntax (GCC default)
gcc -S -O2 -fverbose-asm foo.c -o foo.s
# Intel syntax
gcc -S -masm=intel -O2 foo.c -o foo.s
# From GDB
(gdb) disassemble /s main # with source
(gdb) x/20i $rip
# From objdump
objdump -d -M intel -S prog # Intel + source (needs -g)
2. x86-64 のレジスター
| 64-bit | 32-bit | 16-bit | 8-bit high | 8-bit low | 用途 |
|---|---|---|---|---|---|
%rax | %eax | %ax | %ah | %al | 戻り値/アキュムレーター |
%rbx | %ebx | %bx | %bh | %bl | 呼び出し先保存 |
%rcx | %ecx | %cx | %ch | %cl | 第 4 引数/カウント |
%rdx | %edx | %dx | %dh | %dl | 第 3 引数/第 2 戻り値 |
%rsi | %esi | %si | — | %sil | 第 2 引数 |
%rdi | %edi | %di | — | %dil | 第 1 引数 |
%rbp | %ebp | %bp | — | %bpl | フレームポインター(呼び出し先保存) |
%rsp | %esp | %sp | — | %spl | スタックポインター |
%r8–%r11 | %r8d–%r11d | %r8w–%r11w | — | %r8b–%r11b | 第 5~第 8 引数/呼び出し元保存 |
%r12–%r15 | %r12d–%r15d | %r12w–%r15w | — | %r12b–%r15b | 呼び出し先保存 |
%rip | 命令ポインター | ||||
%rflags | %eflags | ステータスフラグ | |||
%xmm0–%xmm7 | 浮動小数点/SIMD の引数と戻り値 | ||||
%xmm8–%xmm15 | 呼び出し元保存の SIMD レジスター | ||||
%ymm0–%ymm15 | AVX 256 ビット | ||||
%zmm0–%zmm31 | AVX-512 512 ビット |
3. System V AMD64 ABI(Linux、macOS、FreeBSD)
整数/ポインター引数レジスター(順番):
%rdi, %rsi, %rdx, %rcx, %r8, %r9
浮動小数点引数レジスター:
%xmm0–%xmm7
戻り値:
- 整数:
%rax(下位)、%rdx(128 ビットの場合は上位) - 浮動小数点数:
%xmm0(下位)、%xmm1(上位)
呼び出し元保存(スクラッチ): %rax, %rcx, %rdx, %rsi, %rdi, %r8–%r11, %xmm0–%xmm15
呼び出し先保存(保持必須): %rbx, %rbp, %r12–%r15
スタック: call の前に 16 バイト境界に整列します。call は 8 バイトをプッシュするため、プロローグ後の関数エントリー時には 16 バイト境界に整列します。
レッドゾーン: %rsp より下の 128 バイトは、リーフ関数が %rsp を調整せずに使用できます。カーネル/シグナルハンドラーでは使用できません。
4. 一般的な命令パターン
| パターン | 意味 |
|---|---|
mov %rdi, %rax | rdi を rax にコピー |
mov (%rdi), %rax | rdi のアドレスから 8 バイトを読み込む |
mov %rax, 8(%rdi) | rax を rdi+8 に格納 |
lea 8(%rdi), %rax | 実効アドレス rdi+8 を rax に読み込む(メモリーアクセスなし) |
push %rbx | rbx をプッシュ。rsp -= 8 |
pop %rbx | rbx にポップ。rsp += 8 |
call foo | 戻り先アドレスをプッシュし、foo にジャンプ |
ret | 戻り先アドレスをポップし、そこへジャンプ |
xor %eax, %eax | rax をゼロにする(mov $0, %rax より短いエンコーディング) |
test %rax, %rax | rax == 0 の場合に ZF をセット(cmp $0, %rax より低コスト) |
cmp $5, %rdi | rdi - 5 の結果に応じてフラグをセット |
jl label | 符号付き比較で小さい場合にジャンプ |
5. AT&T 構文と Intel 構文
| 特徴 | AT&T | Intel |
|---|---|---|
| オペランドの順序 | ソース、デスティネーション | デスティネーション、ソース |
| レジスターの接頭辞 | %rax | rax |
| 即値の接頭辞 | $42 | 42 |
| メモリーオペランド | 8(%rdi) | [rdi+8] |
| サイズ接尾辞 | movl、movq | —(推論される) |
GCC はデフォルトで AT&T 構文を出力します。Intel 構文を使うには -masm=intel を指定します。
6. インラインアセンブリ(GCC の拡張 asm)
// Basic: increment a register
int x = 5;
__asm__ volatile (
"incl %0"
: "=r"(x) // outputs: =r means write-only register
: "0"(x) // inputs: 0 means same as output 0
: // clobbers: none
);
// CPUID example
uint32_t eax, ebx, ecx, edx;
__asm__ volatile (
"cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(1) // input: leaf 1
);
// Atomic increment
static inline int atomic_inc(volatile int *p) {
int ret;
__asm__ volatile (
"lock; xaddl %0, %1"
: "=r"(ret), "+m"(*p)
: "0"(1)
: "memory"
);
return ret + 1;
}
制約コード:
"r"— 任意の汎用レジスター"m"— メモリーオペランド"i"— 即値整数"a"、"b"、"c"、"d"— 特定のレジスター(%rax、%rbx、%rcx、%rdx)"="接頭辞 — 出力(書き込み専用)"+"接頭辞 — 読み書き"memory"clobber — メモリーが変更される可能性があることをコンパイラーに伝える(バリア)
7. SSE/AVX 組み込み関数(インラインアセンブリより推奨)
#include <immintrin.h> // includes all x86 SIMD headers
// Add 8 floats at once with AVX
__m256 a = _mm256_loadu_ps(arr_a); // load 8 floats (unaligned)
__m256 b = _mm256_loadu_ps(arr_b);
__m256 c = _mm256_add_ps(a, b);
_mm256_storeu_ps(result, c);
コンパイル時に CPU サポートを確認します:-mavx2 または -march=native。
実行時に確認します:__builtin_cpu_supports("avx2")。
レジスターと命令の完全なリファレンスについては、references/reference.md を参照してください。
関連スキル
- AArch64/ARM アセンブリには
skills/low-level-programming/assembly-armを使用します -S -masm=intelフラグの詳細についてはskills/compilers/gccを使用します- アセンブリをステップ実行するには(
si、ni、x/i)、skills/debuggers/gdbを使用します