Claude Skill

assembly-x86

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.

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download outlinedriven-outline-driven-development-.devin_skills_assembly-x86-b0e8ce8.zip · 4 KB
Part of outlinedriven/outline-driven-development — 145 skills

Install

skills CLI npx skills add https://github.com/OutlineDriven/outline-driven-development/tree/main/.devin/skills/assembly-x86
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install outlinedriven-outline-driven-development@llmmart
Git git clone https://github.com/OutlineDriven/outline-driven-development.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole outlinedriven/outline-driven-development collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

x86-64 assembly

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

Field Bound contract
Trigger The 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.
Authority Read-only. The skill explains and drafts; edits land through the normal coding path. No remote mutation.
Side effect None.
Done The 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.
Register 32-bit view Role
rax eax Accumulator, 1st return value, caller saved
rbx ebx Base, callee saved
rcx ecx 4th argument, caller saved
rdx edx 3rd argument, 2nd return value, caller saved
rsi esi 2nd argument, caller saved
rdi edi 1st argument, caller saved
rbp ebp Frame pointer, callee saved
rsp esp Stack pointer
r8 to r11 5th through 8th arguments, caller saved
r12 to r15 Callee saved
rflags flags Condition codes
xmm0 to xmm7 FP and SIMD arguments and returns
xmm8 to xmm15 FP 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.
Pattern Meaning
mov %rdi, -8(%rbp) Store the first argument to a local slot
mov (%rdi), %rax Load 8 bytes from the address in rdi
lea 8(%rdi), %rax Compute an address without memory access
addq $8, %rdi Advance a pointer by one element
push %rbp then pop %rbp Frame save and restore
call func then ret Call pushes the return address, ret pops it
leave mov %rbp, %rsp then pop %rbp
test %rax, %rax Set flags from rax == 0 cheaply
cmp $0, %rax Same flag result, one byte longer
sete %al Copy ZF into a byte register
cmovne %rdx, %rax Conditional 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&T Intel
mov %rax, %rbx mov rbx, rax
mov $8, %rax mov 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 class Behavior
Crash after a call in hand-written asm Stack misalignment. Re-align rsp to 16 before every call site.
Inline asm result wrong at -O2 Missing volatile, a wrong constraint, or a missing "memory" clobber. Fix the declaration, not the build flags.
lock prefix rejected The destination is a register or the assembler is 16-bit mode. lock needs a memory destination.
Intel-syntax source fails to build The file mixes syntaxes. Convert with objdump -M intel as reference, and compile with one syntax.
Value lost across a call It 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.

Files (outline-driven-development)
  • agents
    • openai.yaml 197 B
      interface:
        display_name: "Assembly X86"
        short_description: "Use when reading GCC or Clang x86-64 assembly, writing inline asm, decoding AT&T syntax, or applying System V AMD64 register rules."
      
  • references
    • reference.md 4 KB
      # x86-64 assembly reference
      
      Sources: Intel SDM, the System V AMD64 ABI, and GCC inline asm documentation.
      
      ## Data movement
      
      | Instruction | Effect |
      |-------------|--------|
      | `mov src, dst` | Copy |
      | `movzx src, dst` | Copy with zero extend |
      | `movsx src, dst` | Copy with sign extend |
      | `lea mem, reg` | Compute the address into a register, no memory access |
      | `push reg` | Push onto the stack |
      | `pop reg` | Pop from the stack |
      | `xchg a, b` | Exchange operands, implicit `LOCK` for memory |
      | `cmpxchg a, b` | Compare and exchange, sets `ZF` |
      
      ## Arithmetic
      
      | Instruction | Effect |
      |-------------|--------|
      | `add src, dst` | `dst += src` |
      | `sub src, dst` | `dst -= src` |
      | `imul r/m` | Signed multiply, `rdx:rax = rax * operand` in one-operand form |
      | `mul r/m` | Unsigned multiply, same two-operand split |
      | `idiv r/m` | Signed divide, quotient in `rax`, remainder in `rdx` |
      | `div r/m` | Unsigned divide, same split |
      | `inc`, `dec` | Increment, decrement without touching `CF` |
      | `neg dst` | Two's complement negate |
      
      ## Bit operations
      
      | Instruction | Effect |
      |-------------|--------|
      | `and`, `or`, `xor`, `not` | Bitwise logic |
      | `shl`/`sal` | Shift left |
      | `shr` | Shift right, logical |
      | `sar` | Shift right, arithmetic |
      | `rol`, `ror`, `rcl`, `rcr` | Rotates through carry or not |
      | `bsf src, dst` | Index of lowest set bit |
      | `bsr src, dst` | Index of highest set bit |
      | `tzcnt`, `lzcnt` | Trailing and leading zero counts, BMI or ABM |
      | `popcnt` | Count set bits |
      | `bt`, `bts`, `btr`, `btc` | Bit test and set, reset, complement |
      
      ## Comparison and branching
      
      | Instruction | Effect |
      |-------------|--------|
      | `cmp a, b` | Set flags from `a - b` without storing |
      | `test a, b` | Set flags from `a & b` without storing |
      | `jmp target` | Unconditional jump |
      | `jcc target` | Conditional jump, see the table below |
      | `cmovcc src, dst` | Conditional move |
      | `setcc reg8` | Store the condition as 0 or 1 |
      | `loop label` | Decrement `rcx`, jump when nonzero |
      
      ## rflags bits
      
      | Bit | Flag | Set when |
      |-----|------|----------|
      | CF | Carry | Unsigned overflow |
      | PF | Parity | Low byte has an even count of set bits |
      | AF | Adjust | Carry from bit 3 to bit 4 |
      | ZF | Zero | Result is zero |
      | SF | Sign | Result is negative |
      | TF | Trap | Single step enabled |
      | IF | Interrupt | Interrupts enabled |
      | DF | Direction | String ops go downward |
      | OF | Overflow | Signed overflow |
      
      ## Conditional jumps
      
      | Instruction | Condition | Flags |
      |-------------|-----------|-------|
      | `je`/`jz` | Equal | `ZF=1` |
      | `jne`/`jnz` | Not equal | `ZF=0` |
      | `js` | Sign set | `SF=1` |
      | `jns` | Sign clear | `SF=0` |
      | `jc` | Carry | `CF=1` |
      | `jnc` | No carry | `CF=0` |
      | `jo` | Overflow | `OF=1` |
      | `jno` | No overflow | `OF=0` |
      | `jl`/`jnge` | Signed less | `SF!=OF` |
      | `jle`/`jng` | Signed less or equal | `ZF=1` or `SF!=OF` |
      | `jg`/`jnle` | Signed greater | `ZF=0` and `SF=OF` |
      | `jge`/`jnl` | Signed greater or equal | `SF=OF` |
      | `jb`/`jnae` | Unsigned below | `CF=1` |
      | `jbe`/`jna` | Unsigned below or equal | `CF=1` or `ZF=1` |
      | `ja`/`jnbe` | Unsigned above | `CF=0` and `ZF=0` |
      | `jae`/`jnb` | Unsigned above or equal | `CF=0` |
      
      ## SIMD header map
      
      | Header | Provides |
      |--------|----------|
      | `<xmmintrin.h>` | SSE, `__m128` |
      | `<emmintrin.h>` | SSE2, `__m128d` and `__m128i` |
      | `<pmmintrin.h>` | SSE3 |
      | `<tmmintrin.h>` | SSSE3 |
      | `<smmintrin.h>` | SSE4.1 |
      | `<nmmintrin.h>` | SSE4.2 |
      | `<immintrin.h>` | Everything through AVX-512, use this one |
      
      ## Prologue patterns
      
      Frame pointer kept:
      
      ```asm
      push %rbp
      mov  %rsp, %rbp
      sub  $N, %rsp          # allocate locals, keep rsp 16-byte aligned
      # body
      leave                  # mov %rbp, %rsp; pop %rbp
      ret
      ```
      
      Frame pointer omitted, the default at `-O2`:
      
      ```asm
      sub $N, %rsp
      # body, locals addressed through rsp
      add $N, %rsp
      ret
      ```
      
      Callee-saved registers used by the body:
      
      ```asm
      push %rbx
      push %r12
      push %r13
      # body that uses rbx, r12, r13
      pop %r13
      pop %r12
      pop %rbx
      ret
      ```
      
      Restore in reverse push order. On Linux the kernel is built with `-mno-red-zone`, so kernel-mode code never relies on the 128-byte red zone.
      
  • SKILL.md 6 KB
    ---
    name: assembly-x86
    description: '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.'
    ---
    
    # x86-64 assembly
    
    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
    
    | Field | Bound contract |
    |---|---|
    | Trigger | The 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. |
    | Authority | Read-only. The skill explains and drafts; edits land through the normal coding path. No remote mutation. |
    | Side effect | None. |
    | Done | The 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.
    
    ```bash
    gcc -O2 -S -fverbose-asm foo.c -o foo.s
    gcc -O2 -c foo.c -o foo.o && objdump -d -M intel foo.o
    ```
    
    2. Map registers by role. Done when: every register in the fragment is classified.
    
    | Register | 32-bit view | Role |
    |----------|-------------|------|
    | `rax` | `eax` | Accumulator, 1st return value, caller saved |
    | `rbx` | `ebx` | Base, callee saved |
    | `rcx` | `ecx` | 4th argument, caller saved |
    | `rdx` | `edx` | 3rd argument, 2nd return value, caller saved |
    | `rsi` | `esi` | 2nd argument, caller saved |
    | `rdi` | `edi` | 1st argument, caller saved |
    | `rbp` | `ebp` | Frame pointer, callee saved |
    | `rsp` | `esp` | Stack pointer |
    | `r8` to `r11` | | 5th through 8th arguments, caller saved |
    | `r12` to `r15` | | Callee saved |
    | `rflags` | `flags` | Condition codes |
    | `xmm0` to `xmm7` | | FP and SIMD arguments and returns |
    | `xmm8` to `xmm15` | | FP 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`.
    
    3. 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.
    
    ```asm
    push rbp
    mov  rbp, rsp
    sub  rsp, 16        # keep rsp a multiple of 16 before call sites
    ```
    
    4. Read the recurring instruction shapes. Done when: each line in the fragment parses.
    
    | Pattern | Meaning |
    |---------|---------|
    | `mov %rdi, -8(%rbp)` | Store the first argument to a local slot |
    | `mov (%rdi), %rax` | Load 8 bytes from the address in `rdi` |
    | `lea 8(%rdi), %rax` | Compute an address without memory access |
    | `addq $8, %rdi` | Advance a pointer by one element |
    | `push %rbp` then `pop %rbp` | Frame save and restore |
    | `call func` then `ret` | Call pushes the return address, `ret` pops it |
    | `leave` | `mov %rbp, %rsp` then `pop %rbp` |
    | `test %rax, %rax` | Set flags from `rax == 0` cheaply |
    | `cmp $0, %rax` | Same flag result, one byte longer |
    | `sete %al` | Copy `ZF` into a byte register |
    | `cmovne %rdx, %rax` | Conditional move, branchless select |
    
    5. 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&T | Intel |
    |------|-------|
    | `mov %rax, %rbx` | `mov rbx, rax` |
    | `mov $8, %rax` | `mov rax, 8` |
    | `movb %al, (%rdi)` | `mov byte ptr [rdi], al` |
    | Default in GCC | `-masm=intel` or `objdump -M intel` |
    
    6. 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.
    
    ```c
    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;
    }
    ```
    
    ```c
    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
    }
    ```
    
    7. 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 class | Behavior |
    |---|---|
    | Crash after a `call` in hand-written asm | Stack misalignment. Re-align `rsp` to 16 before every call site. |
    | Inline asm result wrong at `-O2` | Missing `volatile`, a wrong constraint, or a missing `"memory"` clobber. Fix the declaration, not the build flags. |
    | `lock` prefix rejected | The destination is a register or the assembler is 16-bit mode. `lock` needs a memory destination. |
    | Intel-syntax source fails to build | The file mixes syntaxes. Convert with `objdump -M intel` as reference, and compile with one syntax. |
    | Value lost across a call | It 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`.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related