x86-64 assembly

SkillDev tools

Use when reading GCC or Clang x86-64 assembly, writing inline asm, decoding AT&T syntax, or applying System V AMD64 register rules. Not for SIMD intrinsic selection: use simd-intrinsics.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the x86-64 assembly skill

What this skill tells your AI

The instructions your AI receives, as published by outlinedriven/outline-driven-development in .devin/skills/assembly-x86/SKILL.md and read by ahel’s review.

GCC and Clang emit AT&T syntax by default. This skill reads that output, writes inline asm, and keeps register use inside the System V AMD64 ABI.

Contract

FieldBound contract
TriggerThe task reads compiler assembly output, writes inline asm in C or C++, decides AT&T versus Intel syntax, or explains calling conventions and stack layout in a disassembly.
AuthorityRead-only. The skill explains and drafts; edits land through the normal coding path. No remote mutation.
Side effectNone.
DoneThe drafted assembly assembles with gcc -c or clang -c, or the compiler output under discussion is explained register by register.

Inputs

  • The C or C++ source, compiler output, or assembly fragment: required.
  • The compiler: required. AT&T versus Intel output and inline asm details follow it.
  • The ABI: required. System V for Linux and macOS; the Microsoft x64 ABI changes the register map entirely.

Procedure

  1. Generate the baseline. Read the compiler's own output before writing any. Done when: the disassembly of the function under discussion is on screen.
gcc -O2 -S -fverbose-asm foo.c -o foo.s
gcc -O2 -c foo.c -o foo.o && objdump -d -M intel foo.o
  1. Map registers by role. Done when: every register in the fragment is classified.
Register32-bit viewRole
raxeaxAccumulator, 1st return value, caller saved
rbxebxBase, callee saved
rcxecx4th argument, caller saved
rdxedx3rd argument, 2nd return value, caller saved
rsiesi2nd argument, caller saved
rdiedi1st argument, caller saved
rbpebpFrame pointer, callee saved
rspespStack pointer
r8 to r115th through 8th arguments, caller saved
r12 to r15Callee saved
rflagsflagsCondition codes
xmm0 to xmm7FP and SIMD arguments and returns
xmm8 to xmm15FP and SIMD scratch, caller saved

System V argument order: integer and pointer args in rdi, rsi, rdx, rcx, r8, r9, then the stack; float and vector args in xmm0 to xmm7.

  1. Respect the stack rules. rsp stays 16-byte aligned before a call, because the call pushes 8 bytes and the callee expects alignment. The red zone is the 128 bytes below rsp that leaf functions may use without adjusting rsp. Kernel code compiles with -mno-red-zone because interrupts do not honor it. Done when: the drafted prologue keeps the alignment and names the red-zone choice.
push rbp
mov  rbp, rsp
sub  rsp, 16        # keep rsp a multiple of 16 before call sites
  1. Read the recurring instruction shapes. Done when: each line in the fragment parses.
PatternMeaning
mov %rdi, -8(%rbp)Store the first argument to a local slot
mov (%rdi), %raxLoad 8 bytes from the address in rdi
lea 8(%rdi), %raxCompute an address without memory access
addq $8, %rdiAdvance a pointer by one element
push %rbp then pop %rbpFrame save and restore
call func then retCall pushes the return address, ret pops it
leavemov %rbp, %rsp then pop %rbp
test %rax, %raxSet flags from rax == 0 cheaply
cmp $0, %raxSame flag result, one byte longer
sete %alCopy ZF into a byte register
cmovne %rdx, %raxConditional move, branchless select
  1. Choose a syntax and stay in it. AT&T puts the source operand first and prefixes registers and immediates; Intel puts the destination first. Done when: the listing and the written code use one syntax.
AT&TIntel
mov %rax, %rbxmov rbx, rax
mov $8, %raxmov rax, 8
movb %al, (%rdi)mov byte ptr [rdi], al
Default in GCC-masm=intel or objdump -M intel
  1. Write inline asm with the extended syntax. The template lists outputs, inputs, and clobbers. Constraint codes: r general register, a/b/c/d specific ones, m memory, i immediate. Tell the compiler about memory effects with "memory". Done when: the fragment compiles and survives optimization with correct results.
static inline long cpuid_leaf(long leaf) {
    long a, b, c, d;
    __asm__ volatile("cpuid"
                     : "=a"(a), "=b"(b), "=c"(c), "=d"(d)
                     : "a"(leaf));
    return a;
}
static inline int atomic_incr(int *p) {
    int ret;
    __asm__ volatile("lock xaddl %0, %1"
                     : "=r"(ret), "+m"(*p)   // +m: read and written
                     : "0"(1));
    return ret;   // returns the previous value
}
  1. Recognize the SSE and AVX headers when reading vector code. <xmmintrin.h> provides SSE, <emmintrin.h> SSE2, and <immintrin.h> everything through AVX-512. For choosing and writing intrinsics use simd-intrinsics. Done when: vector code under discussion is attributed to its instruction set level.

Failure and recovery

Failure classBehavior
Crash after a call in hand-written asmStack misalignment. Re-align rsp to 16 before every call site.
Inline asm result wrong at -O2Missing volatile, a wrong constraint, or a missing "memory" clobber. Fix the declaration, not the build flags.
lock prefix rejectedThe destination is a register or the assembler is 16-bit mode. lock needs a memory destination.
Intel-syntax source fails to buildThe file mixes syntaxes. Convert with objdump -M intel as reference, and compile with one syntax.
Value lost across a callIt sat in a caller-saved register. Move it to rbx, r12 to r15, or spill it.

Output

Annotated assembly or inline asm with register roles, stack alignment stated, and clobbers justified. The full instruction tables, flags register map, conditional jump list, and prologue patterns are in references/reference.md.

Signals

GitHub stars
52
Forks
9
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
assembly-x86
Source
github.com/outlinedriven/outline-driven-development