x86 Assembly

Table of Contents

x86 is a family of instruction set architectures based on the complex instruction set computer (CISC) architecture (unlike RISC-V). Here, we will focus on the 32-bit ISA, called IA-32 or i386. There are also two different syntaxes for IA-32 assembly, Intel and AT&T; the instructions below will use AT&T syntax.

1. Registers

x86 has only 8 general purpose registers (GPR):

Register Description
ax accumulator
bx base
cx counter
dx data
sp stack pointer
bp base pointer
si source index
di destination index

Originally, these GPRs started as 16-bits. The 32-bit registers used in i386 are therefore denoted with the e prefix (e.g. eax for ax) and with the r prefix for 62-bits (e.g. rax for ax). The lower and upper 8 bits of each 16-bit register can also be explicitly addressed by replacing x with either l or h.

In AT&T syntax, registers are addressed using the percent sign (e.g. %eax for eax). Immediates such as constants are preceded by a dollar sign (e.g. $162 for the constant 162).

1.1. Calling Convention

Before calling a function, the caller needs to:

  1. Save caller-saved GPRs onto the stack if needed after the function call.
  2. Push parameters onto the stack in reverse order (e.g. start with the “rightmost” parameter). Add padding before the parameters to ensure a 16-byte alignment.

Then the caller calls the function by pushing the return address onto the stack and jumping to the function. Then, before executing any function logic, the callee needs to:

  1. Push ebp onto the stack and set ebp to be the new esp. This marks the start of a new stack frame.
  2. Allocate stack space for any local variables (i.e. decrement esp).
  3. Save callee-saved GPRs onto the stack if used during the function call.

Then, the callee will perform the function logic. Before returning, the callee needs to:

  1. Store the return value in eax.
  2. Restore callee-saved GPRs from the prologue.
  3. Deallocate local variables (e.g. set esp to be the current ebp).
  4. Restore the caller’s ebp from the stack.
  5. Return from the function by popping the return address that was pushed to the caller and jumping to it.

Finally, after the function call returns back to the caller, we need to:

  1. Remove the parameters from the stack.
  2. Restore caller-saved GPRs from the prologue.

2. Instructions

In AT&T syntax, the source precedes the destination. There are also a few commonly used instructions that will show up in nearly every assembly code due to calling convention:

pushl src    # push src onto stack
popl dest    # pop from stack into dest
call addr    # push return address onto stack and jump to addr
leave        # restore ebp and esp to previous stack frame
ret          # pop return address from stack and jump to it
Last modified: 2026-09-15 14:38