Simple Example: Proving a Simple ARM Program #
This is a line-by-line port of s2n-bignum/arm/tutorial/simple.ml with detailed
correspondence documented. The program consists of two instructions:
0: 8b000022 add x2, x1, x0
4: cb010042 sub x2, x2, x1
We prove that starting with X0 = a and X1 = b, after executing both
instructions, we have X2 = a (the additions and subtractions cancel out).
Following HOL Light's architecture, programs are stored as bytes in memory. The
arm step relation fetches, decodes, and executes instructions from memory.
Machine Code #
The simple program as a byte sequence (machine code).
ARM is little-endian, so:
- Bytes [0x22, 0x00, 0x00, 0x8b] encode instruction 0x8b000022 = ADD X2, X1, X0
- Bytes [0x42, 0x00, 0x01, 0xcb] encode instruction 0xcb010042 = SUB X2, X2, X1
Specification #
The specification follows HOL Light's ensures arm style:
ensures arm
(\s. aligned_bytes_loaded s (word pc) simple_mc /\
read PC s = word pc /\
read X0 s = word a /\
read X1 s = word b)
(\s. read PC s = word (pc+8) /\
read X2 s = word a)
(MAYCHANGE [PC;X2])
Source: s2n-bignum/arm/tutorial/simple.ml:65-84
Precondition: program loaded, PC at start, registers initialized.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Postcondition: PC advanced, X2 contains a.
Equations
- Bignum.Arm.Tutorial.simple_post pc a s = (s.read_reg Bignum.Arm.Reg.PC = Bignum.Word64.ofNat (pc + 8) ∧ s.read_reg Bignum.Arm.Reg.X2 = Bignum.Word64.ofNat a)
Instances For
Symbolic Execution Helpers #
To prove correctness, we need to show that when bytes are loaded in memory,
arm_decode succeeds and returns the expected instruction.
Decode the first instruction (ADD X2, X1, X0) from loaded bytes.
The proof connects aligned_bytes_loaded (which gives us byte values at each offset)
to arm_decode (which reads 4 bytes and decodes them).
This corresponds to HOL Light's ARM_MK_EXEC_RULE which pre-computes decode results.
In Lean, we prove it as a theorem using the concrete byte values.
Decode the second instruction (SUB X2, X2, X1) from loaded bytes.
Main Correctness Theorem #
The proof follows HOL Light's structure:
- ENSURES_INIT_TAC - establish initial state
- ARM_STEPS_TAC (1--2) - symbolic execution of instructions
- ENSURES_FINAL_STATE_TAC - verify postcondition
- WORD_RULE - discharge word arithmetic
The key insight:
- After instruction 1 (ADD): X2 = word(a + b)
- After instruction 2 (SUB): X2 = word((a + b) - b) = word(a)
Main correctness theorem: the simple program satisfies its specification. This corresponds to HOL Light's SIMPLE_SPEC theorem.