What is the difference between assembly language of x86 and x64 architecture?

Learn what is the difference between assembly language of x86 and x64 architecture? with practical examples, diagrams, and best practices. Covers assembly, x86, x86-64 development techniques with v...

x86 vs. x64 Assembly: A Deep Dive into Architecture Differences

Hero image for What is the difference between assembly language of x86 and x64 architecture?

Explore the fundamental differences between x86 (32-bit) and x64 (64-bit) assembly languages, focusing on registers, addressing modes, instruction sets, and calling conventions.

Understanding the nuances between x86 and x64 assembly language is crucial for low-level programming, reverse engineering, and performance optimization. While x64 is an extension of x86, it introduces significant changes that impact how code is written and executed. This article will break down these differences, providing a clear comparison of their architectural features.

Evolution from x86 to x64

The x86 architecture, originally introduced by Intel, dominated the personal computing landscape for decades. It's a Complex Instruction Set Computer (CISC) architecture known for its variable-length instructions and rich instruction set. As computing demands grew, particularly for larger memory addressing and increased computational power, the limitations of 32-bit systems became apparent. The x64 architecture (also known as x86-64, AMD64, or Intel 64) was developed to extend x86 capabilities to 64 bits, allowing for significantly larger memory addressing and introducing new registers and instructions.

flowchart TD
    A[x86 Architecture (32-bit)] --> B{Need for more memory & power}
    B --> C[x64 Architecture (64-bit)]
    C --> D["Expanded Registers (e.g., RAX, R8-R15)"]
    C --> E["64-bit Addressing (up to 16 Exabytes)"]
    C --> F["New Instruction Set Extensions (e.g., SSE2)"]
    C --> G["Revised Calling Conventions"]

Evolution from x86 to x64 Architecture

Key Architectural Differences

The transition to x64 brought several fundamental changes that directly affect assembly programming. These include an expanded general-purpose register set, a larger address space, and modifications to instruction encoding and calling conventions.

Registers: The Core of the CPU

One of the most significant differences lies in the CPU's general-purpose registers (GPRs). x86 provides 8 GPRs, primarily 32-bit, while x64 doubles this to 16 GPRs, all of which are 64-bit. This expansion greatly enhances performance by reducing the need to spill values to memory.

Hero image for What is the difference between assembly language of x86 and x64 architecture?

Comparison of x86 and x64 General-Purpose Registers

x86 (32-bit) Registers:

  • EAX, EBX, ECX, EDX: General-purpose data registers.
  • ESI, EDI: Source and destination index registers, often used for string operations.
  • EBP: Base pointer, typically used to point to the base of the stack frame.
  • ESP: Stack pointer, points to the top of the stack.

x64 (64-bit) Registers:

  • The original 8 x86 registers are extended to 64-bit: RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP.
  • 8 new general-purpose registers are introduced: R8, R9, R10, R11, R12, R13, R14, R15.
  • Each 64-bit register can be accessed in smaller sizes (e.g., RAX can be accessed as EAX (32-bit), AX (16-bit), AL/AH (8-bit)).
  • The new registers R8-R15 also have 32-bit (R8D-R15D), 16-bit (R8W-R15W), and 8-bit (R8B-R15B) counterparts.

Addressing Modes and Memory Access

The most apparent change in x64 is the ability to address a much larger memory space. x86 is limited to 4GB (2^32 bytes) of virtual memory, whereas x64 can theoretically address 16 exabytes (2^64 bytes). In practice, current implementations typically support 48-bit or 52-bit virtual addressing. This larger address space means pointers and addresses are 64-bit wide, requiring more memory for storage and potentially affecting cache performance if not managed carefully.

; x86 assembly: Move 32-bit value to EAX
MOV EAX, [EBX + ECX*4 + 0x10]

; x64 assembly: Move 64-bit value to RAX
MOV RAX, [RBX + RCX*8 + 0x20]

Example of memory addressing in x86 vs. x64

Calling Conventions

Calling conventions define how functions pass arguments and return values, and how registers are preserved. This is one of the most critical differences when interoperating between 32-bit and 64-bit code, or even between different 64-bit operating systems.

x86 Calling Conventions (e.g., cdecl, stdcall):

  • Arguments are typically pushed onto the stack from right to left.
  • Return values are usually in EAX (for 32-bit values) or EDX:EAX (for 64-bit values).
  • Caller or callee cleans up the stack depending on the convention.

x64 Calling Conventions (e.g., Microsoft x64, System V AMD64 ABI):

  • Microsoft x64 Calling Convention (Windows):
    • First four integer/pointer arguments are passed in RCX, RDX, R8, R9.
    • Additional arguments are pushed onto the stack.
    • Floating-point arguments use XMM0 through XMM3.
    • Return values are in RAX (integer/pointer) or XMM0 (floating-point).
    • Caller is responsible for stack cleanup.
  • System V AMD64 ABI (Linux, macOS):
    • First six integer/pointer arguments are passed in RDI, RSI, RDX, RCX, R8, R9.
    • Additional arguments are pushed onto the stack.
    • First eight floating-point arguments use XMM0 through XMM7.
    • Return values are in RAX (integer/pointer) or XMM0 (floating-point).
    • Caller is responsible for stack cleanup.
graph TD
    subgraph x86 Calling Convention (cdecl)
        A[Arguments Pushed onto Stack] --> B[Function Call]
        B --> C[Return Value in EAX/EDX:EAX]
        C --> D[Caller Cleans Stack]
    end

    subgraph x64 Calling Convention (Microsoft)
        E[Args in RCX, RDX, R8, R9] --> F[Function Call]
        F --> G[Return Value in RAX/XMM0]
        G --> H[Caller Cleans Stack]
    end

    subgraph x64 Calling Convention (System V)
        I[Args in RDI, RSI, RDX, RCX, R8, R9] --> J[Function Call]
        J --> K[Return Value in RAX/XMM0]
        K --> L[Caller Cleans Stack]
    end

Simplified Comparison of x86 and x64 Calling Conventions

Instruction Set Extensions

While many core instructions remain the same, x64 introduced new instructions and extended existing ones to handle 64-bit operands. Furthermore, modern x64 processors often include advanced instruction set extensions like SSE2, SSE3, SSSE3, SSE4, AVX, and AVX2, which are not always present or fully supported on older x86 processors. These extensions provide powerful capabilities for vectorized operations, significantly boosting performance for tasks like multimedia processing and scientific computing.

; x86: Add two 32-bit integers
ADD EAX, EBX

; x64: Add two 64-bit integers
ADD RAX, RBX

; x64: Example of using a new register (R8)
MOV R8, 0x123456789ABCDEF0
ADD RAX, R8

Basic arithmetic operations in x86 vs. x64 assembly