Assembly Language - Registers

A register is a high-speed storage unit inside the CPU, and is the most frequently manipulated object in assembly programming. Understanding registers is the key first step to learning assembly language well.


What is a Register

Registers are integrated inside the CPU chipUltra-high-speed small memory storage, used to temporarily store instructions, data, and addresses.

Unlike memory, registers are embedded inside the CPU. The CPU can access registers with almost zero latency, whereas accessing memory requires dozens to hundreds of clock cycles.

In assembly language, the vast majority of operations revolve around registers—data is loaded from memory into registers, operations are performed in registers, and then the results are stored back to memory.

You can think of registers as the CPU's "workbench." Tools on the workbench are available at any time, while memory is like a warehouse that you need to walk over to fetch and store items.


x86 32-bit Register Classification

The x86 32-bit architecture provides many types of registers, each with different purposes. The following figure shows the complete register classification:

x86 32位寄存器分类概览

Below we introduce each type of register in detail:


General Purpose Registers

General Purpose RegistersThey are the most commonly used registers, used to store operation data and temporary results.

x86 provides 8 32-bit general-purpose registers:

32-bit16-bitLow 8 bitsHigh 8 bits (of low 16 bits)Main purpose
EAXAXALAHAccumulator, stores function return values and arithmetic operation results
EBXBXBLBHBase register, often used to store memory base addresses
ECXCXCLCHCounter, often used for loop counting and shifts
EDXDXDLDHData register, stores the high-order results of multiplication and division
ESISISIL-Source index register, source address for string operations
EDIDIDIL-Destination index register, destination address for string operations
EBPBPBPL-Base pointer, points to the bottom of the current stack frame
ESPSPSPL-Stack pointer, always points to the top of the stack

Naming convention: The E prefix means Extended (extended to 32 bits), and the X suffix indicates that it can be split into high and low bytes.

Example

; File path: register_parts.asm
; Demonstrate access to different parts of registers

section .text
    global _start

_start:
    mov eax, 0x12345678     ; Complete 32-bit register
    ; At this point: EAX = 0x12345678
    ; AX = 0x5678 (low 16 bits)
    ; AH = 0x56 (high 8 bits, i.e., the high 8 bits of AX)
    ; AL = 0x78 (low 8 bits)

    mov ax, 0xAABB          ; Modify AX (low 16 bits)
    ; At this point: EAX = 0x1234AABB (the high 16 bits remain unchanged!)
    ;       AX  = 0xAABB
    ;       AL  = 0xBB

    mov al, 0xCC            ; Modify AL (lowest 8 bits)
    ; At this point: EAX = 0x1234AACC (only the low 8 bits changed)
    ;       AX  = 0xAACC
    ;       AL  = 0xCC

    mov eax, 1
    mov ebx, 0
    int 0x80

When modifying the low 16 bits of a 32-bit register (such as AX), the high 16 bits remain unchanged. However, when a 32-bit register is used as the destination operand, the entire 32 bits are overwritten. This is a common source of errors for beginners.


Segment Registers

Segment registers are used to specify the currently used memory segment:

RegisterNamePurpose
CSCode segment registerPoints to the segment where the current instruction is located
DSData segment registerPoints to the segment where data is located
SSStack segment registerPoints to the segment where the stack is located
ESExtra segment registerAdditional data segment
FSExtra segment registerGeneral purpose, often used for thread-local storage
GSExtra segment registerGeneral-purpose, commonly used for thread-local storage

When programming in 32-bit protected mode, the operating system has already set up the segment registers, so you usually don't need to modify them manually.


Pointer and Index Registers

These registers are mainly used to access memory and store memory addresses:

RegisterFull namePurpose
EIPInstruction PointerPoints to the address of the next instruction to be executed by the CPU (not directly accessible)
ESPStack PointerPoints to the top of the stack; PUSH/POP instructions automatically adjust it
EBPBase PointerPoints to the bottom of the current function's stack frame, used to access function parameters and local variables
ESISource IndexSource address for string/memory operations
EDIDestination IndexDestination address for string/memory operations

ESP and EBP cannot be used freely as ordinary general-purpose registers. ESP points to the top of the stack, and push/pop/call/ret all change it; EBP is key to accessing function parameters. Modifying them arbitrarily will cause the program to crash.


Flag Register (EFLAGS)

EFLAGSIt is a 32-bit register, each bit represents a status flag.

You cannot directly read or write the entire EFLAGS, but the CPU automatically updates these flag bits based on operation results, and conditional jump instructions use them to decide whether to jump.

Flag bitNameMeaning
CFCarry FlagSet to 1 when unsigned arithmetic produces a carry/borrow
PFParity FlagSet to 1 when the number of 1s in the low 8 bits of the result is even
AFAuxiliary Carry FlagSet to 1 when there is a carry/borrow from the low 4 bits to the high 4 bits
ZFZero FlagSet to 1 when the operation result is 0
SFSign FlagSet to 1 when the operation result is negative (equal to the most significant bit of the result)
OFOverflow FlagSet to 1 when signed arithmetic overflows

Example

; File path: flags_demo.asm
; Demonstrates the effect of arithmetic on flag bits

section .text
    global _start

_start:
    mov eax, 10
    sub eax, 10         ; 10 - 10 = 0
    ; ZF = 1 (result is zero)
    ; SF = 0 (result is non-negative)
    ; CF = 0 (no borrow)

    mov eax, 0xFFFFFFFF
    add eax, 1          ; 0xFFFFFFFF + 1 = 0x100000000 (exceeds 32 bits)
    ; ZF = 1 (32-bit result is 0)
    ; CF = 1 (carry produced)
    ; OF = 0 (no overflow from a signed perspective)

    mov eax, 1
    mov ebx, 0
    int 0x80

Register Usage Conventions

In actual programming, some registers have conventional uses—calledCalling Convention:

RegisterPurpose in the calling convention
EAXStore function return value
ECXCounter (loop count)
EDXStore the high part of division results, extend EAX
EBX、ESI、EDI、EBPCallee-saved: the called function must save and restore
EAX、ECX、EDXCaller-saved: the caller is responsible for saving

When writing your own assembly programs, you don't have to strictly follow the calling convention. But if you're mixing with C, you must follow the cdecl calling convention.

Other extensions