关于 assembly-x86
assembly-x86 是一项引导 Agent 学习 x86-64 汇编的技能,内容从解读编译器输出延伸到 ABI、内联汇编和 SIMD intrinsic。
主要功能
- 01阅读编译器生成的汇编
- 02理解寄存器与 System V ABI
- 03比较 AT&T 和 Intel 语法
- 04编写 GCC 扩展内联汇编
- 05使用 SSE 和 AVX intrinsic
- 06识别常见指令模式
适用场景
- 01检查 C 程序的 GCC 输出
- 02理解函数参数与返回值
- 03在 C 中编写内联汇编
- 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 汇编
用途
指导 Agent 学习 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 位 | 32 位 | 16 位 | 高 8 位 | 低 8 位 | 用途 |
|---|---|---|---|---|---|
%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 语法。使用 -masm=intel 可指定 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。
相关技能
- 使用
skills/low-level-programming/assembly-arm处理 AArch64/ARM 汇编 - 使用
skills/compilers/gcc了解-S -masm=intel标志的详细信息 - 使用
skills/debuggers/gdb单步调试汇编(si、ni、x/i)
评论
支持 Markdown