x86-64 and the AMD64 Extension

AMD introduced AMD64, its 64-bit extension to x86, in 2003 with the Opteron and Athlon 64. Intel later implemented a closely compatible extension, initially called Extended Memory 64 Technology and now generally Intel 64. The common technical names are x86-64 and AMD64; Microsoft often uses x64. They identify the same broad ISA family in ordinary platform discussion, not three unrelated processor architectures. Exact optional instruction extensions still depend on a particular CPU and operating system.

Long mode and its execution submodes

Long mode is enabled by operating-system setup of protected-mode and paging controls; it is not merely “using a 64-bit register.” Its 64-bit submode supplies 64-bit general-purpose operations and addresses, while compatibility submode lets a 64-bit operating system run many 16- or 32-bit protected-mode applications. Legacy real mode and ordinary protected mode remain available outside long mode for boot and older operating systems. This layered arrangement made transition possible without claiming that all old drivers, DOS programs, or kernel interfaces would run unchanged.

Execution environmentTypical useKey limit
64-bit modeModern 64-bit kernels and applicationsRequires 64-bit-aware OS and ABI.
Compatibility mode32-bit or 16-bit protected applications under a 64-bit OSIt is not real mode and does not make old kernel drivers compatible.
Legacy modesBoot firmware, old OSs, and virtual machinesDo not provide long-mode register/address semantics.

AMD64 expands the familiar eight general registers to 64 bits and adds R8 through R15, yielding sixteen general-purpose registers. RAX, RBX, and the other older names refer to the extended registers; writing a 32-bit subregister such as EAX zero-extends its corresponding 64-bit register in 64-bit mode. The architecture also extends SIMD register availability and retains the condition flags and much x86 instruction behavior. More registers reduce some compiler spill traffic, but no fixed performance claim follows: program structure and memory behavior still dominate many workloads.

Addresses are not all 64 bits in practice

A 64-bit pointer representation does not mean a machine implements 64 physical address bits or that every bit pattern is a valid virtual address. CPUs implement a specified number of virtual-address and physical-address bits, reported through CPUID and varying by generation. In long mode, implemented virtual addresses use a canonical form: upper bits must replicate the top implemented address bit. Paging translates virtual addresses through page tables to physical addresses. Operating systems choose layouts and may reserve large regions. Therefore “64-bit address space” is useful shorthand but poor capacity arithmetic without the CPU and OS details.

RIP-relative addressing is another consequential feature. Instructions can address data at a displacement from the instruction pointer, supporting position-independent code efficiently. This suits shared libraries and address-space layout choices, but it is not a substitute for relocation information, dynamic linking policy, or security design. The instruction encoding also uses a REX prefix for access to extended registers and 64-bit operand size, preserving much older encoding space while adding capability.

Two important calling conventions

An ABI defines how separately compiled code agrees on calls, data layout, object files, and more. On mainstream Unix-like x86-64 systems, the System V AMD64 ABI passes initial integer or pointer arguments in RDI, RSI, RDX, RCX, R8, and R9; it designates RBX, RBP, and R12–R15 as callee-saved and provides a 128-byte red zone below RSP for suitable leaf-code use. On 64-bit Windows, the x64 calling convention uses RCX, RDX, R8, and R9 for the first four integer or pointer arguments, requires caller-provided shadow space, and has a different preserved-register set. Floating-point/vector argument rules and aggregate handling also differ.

Neither convention is “the x86-64 convention.” Assembly, foreign-function interfaces, debuggers, and binary tooling must use the ABI of their target platform. A 64-bit kernel additionally has its own syscall convention, which need not match C function calls. Mixing object files built for different ABIs without an adapter can corrupt registers, stack alignment, or arguments even though both are x86-64 code.

Compatibility and a continuing name

AMD64 won adoption partly because it preserved a practical 32-bit x86 path while offering a larger register set and address space. Intel’s adoption made it a cross-vendor platform. This history should not become vendor mythology: AMD designed the extension, Intel’s implementation and software ecosystem helped establish the shared target, and operating-system vendors, compiler writers, motherboard makers, cloud providers, and users determined its reach. IA-64 was a separate architecture with a different compatibility story; it is not another name for x86-64.

Today x86-64 is a common host for virtual machines and Emulation, while ARM64 is another common host ISA. Cross-platform Open Source projects must not assume either: source portability, tested build systems, byte order, atomics, and ABI rules still matter. The relevant question is always which ISA, operating system, ABI, and optional features a binary actually requires.

Registers and instruction encoding in use

The additional registers are more consequential than the phrase “64-bit” alone suggests. A compiler can keep more local values, loop counters, and addresses in registers rather than repeatedly saving them to the stack. For example, a function handling several array pointers and bounds can use R8 through R15 as separate working values where 32-bit x86 would often run out of convenient general registers. This may reduce memory traffic, but it is an opportunity rather than a guaranteed speedup; register pressure, instruction selection, cache misses, and calling boundaries still affect generated code.

In 64-bit mode, the REX prefix extends register encodings and can select a 64-bit operand. Its presence has small but visible legacy consequences: the high-byte forms AH, BH, CH, and DH cannot be encoded in an instruction that uses a REX prefix. Code generators normally handle this automatically, but assemblers, binary translators, and disassemblers must implement it correctly. The ISA remains variable length, with old prefixes, ModR/M addressing forms, and new encodings sharing a historical framework. “AMD64 is a clean new ISA” is as misleading as saying it is unchanged 8086.

RIP-relative data access demonstrates both continuity and change. If an instruction at a known address contains a signed displacement, its effective address is computed from the address of the following instruction plus that displacement. A shared object can then refer to nearby constants or tables without embedding its load address in each reference. Position-independent executable code still needs a loader, relocation records for some symbols, and a platform-defined linking model. RIP-relative addressing helps a technique; it does not itself randomize addresses or secure a process.

Virtual, linear, and physical capacity

Long mode uses page tables to translate virtual addresses. Current implementations commonly use multi-level tables, and some support five-level paging, but the number of implemented virtual and physical bits is deliberately reported rather than assumed to be 64. A virtual address is an address in a process’s translation context; a physical address identifies a location presented to RAM and devices after translation. The two spaces can have different widths. A system with a 48-bit virtual-address implementation and fewer physical-address bits can give every process a large sparse virtual range without containing anything close to that amount of installed DRAM.

Canonicality is checked before a noncanonical address can be used as an ordinary long-mode virtual address. On a machine implementing 48 virtual-address bits, bits 63 through 48 must copy bit 47. Thus low canonical addresses and high canonical addresses occupy two ranges, with a noncanonical hole between them. Future-capable terminology is preferable to hard-coding that particular width: CPUID information and the operating system’s paging configuration govern the real limit. User programs should use documented allocation and pointer interfaces, not manufacture addresses from assumptions about a kernel layout.

Page permissions and address translation support isolation, demand allocation, shared libraries, memory-mapped files, and copy-on-write processes. They do not remove the need for bounds checking, safe language runtimes, or correct kernel code. Hardware also has I/O and DMA considerations: an operating system may use an IOMMU to constrain devices, but that is a platform facility distinct from ordinary CPU page tables. Precise terminology prevents an address-space feature from being credited with unrelated security properties.

ABI example and interoperability

Suppose a C function takes five integer-sized arguments. Under the usual System V AMD64 ABI, the first five are placed in RDI, RSI, RDX, RCX, and R8. Under the Microsoft x64 convention, the first four use RCX, RDX, R8, and R9, and the fifth is passed on the stack; the caller also reserves shadow space for register arguments. A hand-written function expecting one convention will read the wrong values if called by code following the other. Both sides must also maintain required stack alignment and preserve the registers assigned to the callee by their ABI.

The System V red zone is another example of a platform rule, not a universal processor feature. Suitable leaf functions can use 128 bytes below the current stack pointer without adjusting it in the SysV user-space ABI. Windows x64 code must not make that assumption. Kernel code can have separate rules because interrupts and context switches change the safety analysis. A compiler’s target triple, platform SDK, and assembler directives are therefore as relevant as instruction syntax when building low-level x86-64 code.

Data models also differ. Most Unix-like 64-bit x86 systems use LP64, where long and pointers are 64 bits, while Windows x64 uses LLP64, where long remains 32 bits and pointers are 64 bits. Fixed-width types such as uint64_t express intent better for interchange formats. Serializing a native C structure is generally unsafe across ABIs because field sizes, alignment, padding, and byte order can differ. The architecture’s little-endian convention is stable, but protocols must define their own representation.

Compatibility in both directions

A 64-bit operating system can often run a 32-bit application through compatibility mode plus appropriate 32-bit libraries and loader support. It cannot normally load a 32-bit kernel driver into a 64-bit kernel: kernel calling conventions, data structures, address assumptions, and security policy differ. Sixteen-bit protected applications have more limited support, and real-mode DOS applications require a virtual machine or emulator on many modern systems. “The CPU supports it” is not a complete answer because firmware, OS policy, drivers, and user-space runtime form the actual environment.

Conversely, a 32-bit OS cannot execute a 64-bit user binary merely because the processor implements AMD64; it lacks the long-mode kernel setup and ABI environment the binary requires. Virtualization can host an older or different guest when the hypervisor exposes a suitable virtual machine, but device drivers, licenses, and firmware still matter. These distinctions are useful when diagnosing whether a failure is an ISA mismatch, an ABI mismatch, a missing library, or absent hardware emulation.

The enduring names—x86-64, AMD64, and x64—are practical labels for this shared extension. They should be accompanied by exact feature tests when software needs AVX, particular cryptographic instructions, virtualization extensions, or a specified paging capability. A portable build that targets baseline x86-64 may run broadly but cannot issue every extension unconditionally. Feature detection, clear minimum requirements, and fallback implementations are more honest than equating a marketing label with one fixed processor.

Sources and further reading