We will build the machine from pure mathematical axioms, one atomic definition at a time. Every claim will be supported by its formal definition.
Axiom 1: The Machine State as a Tuple
A 64-bit x86-64 CPU is a discrete deterministic state machine.
Its core state at any discrete clock step t is a mathematical tuple:
St=⟨R,M,rip⟩
1. Registers (R): A finite set of sixteen named 64-bit words:
R={rax,rbx,rcx,rdx,rsi,rdi,rbp,rsp,r8…r15}
Each register is a function mapping a register name to an integer in {0,…,264−1}:
R:Name→W64
2. Memory (M): A contiguous byte-addressable array:
M:W64→W8
Reading an 8-byte word (64 bits) from address a means
fetching the 8 consecutive bytes starting at address a:
M64[a]=∑k=07M[a+k]⋅28k(Little-Endian representation)
3. Instruction Pointer (rip): A single 64-bit scalar holding the memory address of the next instruction to execute:
rip∈W64
Axiom 2: Operand Syntax (Source → Destination)
In x86-64 AT&T syntax, an instruction is a transition function T:St→St+1.The general syntax is strictly:
OPCODESource,Destination
The value is read from Source, modified by OPCODE, and written to Destination.
- The Dollar Sign Prefix ($):
Denotes an immediate constant (a pure mathematical scalar c∈Z).
$0⟹Value 0
$4⟹Value 4
- The Percent Sign Prefix (%):
Denotes a register name in R.
%rax
Concrete Evidence:
Instruction: movq $0, %rax
- Mathematical Definition: Rt+1[rax]←0
- Proof of Direction:
The source is $0 (left). The destination is %rax (right). The scalar 0 is placed into register rax.
Axiom 3: Address Calculation via Parentheses
Parentheses denote Memory Dereferencing (pointer arithmetic).
If k∈Z is an integer literal and reg∈R, the notation:
k(%reg)
evaluates to the physical memory location at the address:
Effective Address=R[reg]+k
Therefore:
movq Source,k(%reg)⟹M64[R[reg]+k]←Value(Source)
Concrete Evidence for -8(%rbp) and -24(%rbp):
Suppose %rbp currently holds the address 1000 (i.e., R[rbp]=1000).
Effective Address=1000+(−8)=992
The instruction movq $0, -8(%rbp) does:
M64[992]←0
Effective Address=1000+(−24)=976
The instruction subq $1, -24(%rbp) does:
M64[976]←M64[976]−1
Why did the compiler pick 992 and 976?
Because each 64-bit integer takes 8 bytes.
- Byte interval for slot 1: [992,999] (8 bytes wide ⟹ called sum in C).
- Byte interval for slot 2: [976,983] (8 bytes wide ⟹ called n in C).
Let us formalize the four basic arithmetic instructions:
| Instruction | Formal State Transformation | Plain Meaning |
|---|
| movq S, D | D←S | Overwrite D with S. |
| addq S, D | D←D+S | Add S to D, store result in D. |
| subq S, D | D←D−S | Subtract S from D, store result in D. |
| cmpq S2, S1 | Discard (S1−S2), update Flags | Compare: compute S1−S2 only to set flags. |
Crucial Detail on cmpq S2, S1:
The comparison computes Destination minus Source (Second−First).
Therefore, cmpq $0, %rax computes:
If R[rax]>0, the result is positive, and the machine records "Greater Than".
Step-by-Step Mathematical Trace of 3 Instructions
Let the initial state at step t=0 be:
- R[rbp]=1000
- M64[992]=5 (the value at
-8(%rbp))
- R[rax]=10
Step 1: movq $0, -8(%rbp)
- Input State: M64[992]=5
- Transformation: Write immediate constant 0 to address 1000−8=992.
- Output State: M64[992]=0.
Step 2: addq $7, %rax
- Input State: R[rax]=10
- Transformation: R[rax]←R[rax]+7=10+7=17.
- Output State: R[rax]=17.
Step 3: subq $1, -8(%rbp)
- Input State: M64[992]=0
- Transformation: M64[992]←M64[992]−1=0−1=−1.
- Output State: M64[992]=−1 (stored as two's complement 0xFFFFFFFFFFFFFFFF).