ISAisacontractabispecificationcompatibility

The ISA: The Contract Between Software and Hardware

An instruction set architecture is the specification a compiler targets and a processor promises to honour: which instructions exist, which registers they name, how memory behaves, and how addresses are formed. Everything about how that promise is kept is deliberately outside it.

Follow the mechanism

Software view, hardware view

The gap between what you wrote and what the machine does is where this whole domain lives.

The question
What exactly is an instruction set architecture, and where does its authority stop?
What you wrote
My code is compiled for a platform and it runs there. The details are the toolchain's business.
What the hardware does
A published specification defines the instructions, registers, addressing modes and memory ordering rules that any conforming processor must implement. Compilers emit against that contract, and processors are free to implement it however they like.
The ISA is what makes binaries portable across processor generations and vendors. Knowing what is in the contract — and, more usefully, what is not — is what lets you attribute behaviour to the right layer.
SourceCompilerInstructionsFront EndExecutionRegistersCachesMemoryI/OBehavior

What the contract specifies

An ISA specifies the things software must be able to rely on. Which instructions exist and what each computes. How many architectural registers there are and what they are called. How addresses are formed — the addressing modes (Addressing Modes: How an Index Becomes an Address). What sizes and alignments of memory access are permitted. And, critically for multi-threaded code, what ordering guarantees memory operations have (Hardware Memory Models Are Not Language Memory Models).

That last item is easy to overlook and is genuinely part of the contract. Whether one core is guaranteed to observe another core's writes in the order they were issued is an architectural property, not an implementation detail, and it differs between instruction sets in ways that make correct concurrent code non-portable at the assembly level.

The contract's value is compatibility across time. A binary compiled years ago runs on a processor designed years later because both sides honour the same specification — and honouring it is precisely what allows the newer processor to be internally nothing like the older one.

Inside the contract, and outside it
ConcernIn the ISA?Why
Which instructions existYesCompilers must know what they may emit
Number and names of architectural registersYesInstructions encode register names directly
Addressing modesYesAddress formation is part of instruction semantics
Memory ordering guaranteesYesConcurrent code correctness depends on it
Pipeline depth, cache sizes, execution widthNoImplementation choices — see ISA vs Microarchitecture: The Distinction Everything Depends On
Which register holds a function's first argumentNo — that is ABIA software convention layered on top of the ISA
How a system call is madePartly — the instruction is ISA; the numbering is OSThe contract stops at the instruction

Calling conventions are ABI, not ISA

ABI-SPECIFICArgument registers, callee-saved registers and stack alignment are platform ABI decisions. The same ISA carries different ABIs on different operating systems, and code built for one does not interoperate with the other.

This distinction is worth isolating because it is confused constantly. The ISA says a register exists and what instructions can do with it. It does not say that it holds a function's first argument, or that another register must be preserved across calls, or how a struct returned by value is passed. Those are application binary interface decisions — conventions that let separately compiled code interoperate.

The evidence that these are separable is that the same ISA carries different ABIs. Which registers are argument-passing, which are callee-saved and how the stack is aligned at a call boundary differ between platforms that share an instruction set entirely. Code compiled for one will not correctly interoperate with code compiled for the other, despite every instruction being valid on both machines.

The practical payoff arrives when reading disassembly. The instruction semantics come from the ISA manual; the meaning of *which* register a value was placed in comes from the ABI document for that platform. Reaching for the wrong one is a reliable way to misread a function prologue.

The same instruction, two different meanings depending on the ABI in force
  mov  %rdi, %rax        ; ISA says: copy one 64-bit register to another.
                         ; ABI says: rdi held the first integer argument,
                         ;           and rax is where the return value goes.
                         ;           => "return the first argument"

  ; Same instruction, different platform ABI on the same ISA:
  ;   - a different register may carry the first argument
  ;   - a different set of registers may be callee-saved
  ;   - stack alignment requirements at the call may differ
  ;
  ; The instruction is valid either way. The *meaning* is not in the ISA.

Why the contract is drawn where it is

The boundary is chosen to maximise what implementers may change. Everything software genuinely needs to depend on is inside; everything else is left out deliberately, so that processor designers can restructure the machine freely between generations without invalidating any existing binary.

This is the same principle as an API contract in software — and it fails in the same way when the boundary leaks. Software that depends on unspecified behaviour, such as the timing of particular instructions or the size of a cache, works on the machine it was developed on and breaks on the next one. That is not the hardware betraying the contract; it is software having relied on something the contract never promised.

It also explains why ISAs accumulate extensions rather than being redesigned. Removing an instruction breaks binaries; adding one does not. The result is instruction sets that grow monotonically and carry decades of history, which is a compatibility success story that happens to look like accumulated mess.

  • In the contract: instructions, architectural registers, addressing modes, memory ordering.
  • Outside it: caches, pipeline depth, execution width, instruction timing.
  • Adjacent to it: the ABI, which is a software convention on top of the ISA.
  • Why: so implementations can change freely without breaking existing binaries.
  • The failure mode: depending on unspecified behaviour, which works until the next machine.
Where a given dependency puts you
Depending on…Portable across generations?Why
An instruction existingYes, within the declared baselineIt is in the contract
Memory ordering guaranteesYes, within one ISAArchitectural — but differs between ISAs
An instruction's cycle countNoMicroarchitectural; changes between generations
A specific cache sizeNoNot in the contract at all
Argument register placementOnly within one ABIA platform convention, not the ISA

Key points

  • The ISA specifies instructions, architectural registers, addressing modes and memory ordering — what software may rely on.
  • It deliberately omits caches, pipeline depth, width and timing, so implementations can change freely.
  • Calling conventions are ABI, not ISA: the same instruction set carries different ABIs on different platforms.
  • The contract exists to make binaries portable across generations and vendors.
  • Depending on unspecified behaviour works on the machine you tested and breaks on the next one.

Follow the mechanism

The path through the machine, hop by hop — and the conclusions it invites that are wrong.

  1. 1
    Source → compiler: code is lowered to instructions drawn from the target ISA's defined set.
  2. 2
    Compiler → ABI: argument placement, callee-saved registers and stack alignment follow the platform convention, not the ISA.
  3. 3
    Binary → processor: the processor decodes instructions according to the architectural specification it implements.
  4. 4
    Processor → microarchitecture: how those instructions are actually executed is unconstrained by the contract.
  5. 5
    Retirement → architectural state: results become visible in the order and form the ISA promises, whatever happened internally.
What people conclude from this — wrongly
  • "It ran on my machine, so it is a valid binary for this ISA." It may require extensions your deployment target lacks.
  • "The ISA tells me how fast this instruction is." It defines what the instruction computes. Cost is a microarchitectural property.
  • "Calling conventions are part of the instruction set." They are ABI, and they differ between platforms sharing the same ISA.

Consequences, controls and cost

What it causes
  • • A binary compiled years ago runs on hardware designed years later, because both honour the same published contract.
  • • Code that depends on instruction timing or cache size is not portable even across processors of the same ISA.
  • • Object files built with different ABIs on the same ISA cannot be linked together correctly, despite every instruction being valid.
What you can do
  • • Target the ISA baseline your deployment actually guarantees rather than the machine you happen to build on.
  • • Depend only on documented architectural behaviour; treat observed timing as measurement, never as specification.
  • • When reading disassembly, use the ISA manual for semantics and the platform ABI document for register meaning.
  • • Use compiler flags to select instruction set extensions explicitly, so binaries do not silently require newer hardware.
How to see it
  • • Inspect a binary for the instruction set extensions it actually uses before deploying to hardware with a different baseline.
  • • Compare disassembly against the ISA manual for semantics and the platform ABI for register roles when a function boundary looks wrong.
  • • Verify at load time, or at build time, that the required extensions are present rather than discovering it as an illegal instruction fault.
What it costs
  • • Targeting a conservative ISA baseline maximises portability and leaves newer instructions — and their performance — unused.
  • • Targeting a newer baseline produces better code and a binary that will not start on older hardware.

Scope

§224 — what these claims are specific to.

What these claims are specific to
  • ISA-SPECIFICWhat is included in the contract differs between instruction sets; memory ordering guarantees in particular vary substantially between x86-64 and AArch64.
  • ABI-SPECIFICCalling conventions, callee-saved register sets and stack alignment are platform decisions layered on the ISA and differ between operating systems on identical hardware.

Misconceptions

Claim
“The ISA determines how fast a processor is.”
Reality
It determines what the processor must be able to do, not how well it does it. Two implementations of the same ISA can differ in performance by an order of magnitude.
Claim
“Calling conventions are part of the ISA.”
Reality
They are ABI. The same ISA carries different ABIs on different operating systems, and object files built against different ABIs cannot be linked correctly.
Claim
“A binary for an ISA runs on any processor implementing that ISA.”
Reality
Only if it uses no extensions beyond that processor's baseline. Modern instruction sets are large collections of optional extensions, and using one raises your minimum hardware requirement.

Where the rest of this lives

Programming Languages & Runtime Internals
Code generation and target selection

Which ISA baseline and which extensions a compiler targets is a build-time decision that determines both the instructions emitted and the minimum hardware the binary will start on.