FA-89406 / Instruction set emulation / Open access
Stack pointer sticks at zero · case 01
Pushing past the bottom of the stack page overwrites the same byte repeatedly.
ROOT CAUSE
The decrement saturates instead of wrapping within the page.
THE FAILURE
The decrement saturates instead of wrapping within the page.
Unsuccessful approach: A 9-bit wrap leaves the stack page.
Case contract
Input [pc, sp, ops] for an 8-bit stack pointer addressing page 0x100. push stores at 0x100+sp then decrements sp (wrapping in 8 bits); pull increments sp (wrapping) then reads (unwritten bytes read 0). jsr t (3 bytes at pc) pushes (pc+2) high byte then low byte and jumps; rts pulls low then high and resumes at that address + 1 (16-bit wrap). pha v pushes v, pla pulls; both and nop advance pc by 1. Return [[pc, sp, pulled value or None] per op, sorted [address, byte] of written stack memory].
Why this case matters
Emulated call/return must reproduce the exact stack image because programs inspect and manipulate return addresses on the stack.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
pc, sp, ops = args
mem = {}
trace = []
def push(v):
nonlocal sp
mem[0x100 + sp] = v & 0xFF
sp = max(sp - 1, 0)
def pull():
nonlocal sp
sp = (sp + 1) & 0xFF
return mem.get(0x100 + sp, 0)
for op in ops:
got = None
if op[0] == 'jsr':
ret = (pc + 2) & 0xFFFF
push(ret >> 8)
push(ret)
pc = op[1]
elif op[0] == 'rts':
lo = pull()
hi = pull()
pc = ((hi << 8 | lo) + 1) & 0xFFFF
elif op[0] == 'pha':
push(op[1])
pc += 1
elif op[0] == 'pla':
got = pull()
pc += 1
else:
pc += 1
trace.append([pc, sp, got])
return [trace, [[k, mem[k]] for k in sorted(mem)]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 18], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 18]], [[510, 34], [511, 18]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 86], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 86]], [[256, 68], [257, 51], [511, 86]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2289, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2292, 255, None]], [[508, 2], [509, 9], [510, 243], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 129, [['jsr', 4660], ['rts']]], [[[4660, 127, None], [0, 129, None]], [[384, 255], [385, 255]]])], [('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 19], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 19]], [[510, 34], [511, 19]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 87], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 87]], [[256, 68], [257, 51], [511, 87]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2290, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2293, 255, None]], [[508, 2], [509, 9], [510, 244], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 130, [['jsr', 4660], ['rts']]], [[[4660, 128, None], [0, 130, None]], [[385, 255], [386, 255]]])], [('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 20], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 20]], [[510, 34], [511, 20]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 88], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 88]], [[256, 68], [257, 51], [511, 88]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2291, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2294, 255, None]], [[508, 2], [509, 9], [510, 245], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 131, [['jsr', 4660], ['rts']]], [[[4660, 129, None], [0, 131, None]], [[386, 255], [387, 255]]])], [('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 21], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 21]], [[510, 34], [511, 21]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 89], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 89]], [[256, 68], [257, 51], [511, 89]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2292, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2295, 255, None]], [[508, 2], [509, 9], [510, 246], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 132, [['jsr', 4660], ['rts']]], [[[4660, 130, None], [0, 132, None]], [[387, 255], [388, 255]]])], [('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 22], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 22]], [[510, 34], [511, 22]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 90], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 90]], [[256, 68], [257, 51], [511, 90]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2293, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2296, 255, None]], [[508, 2], [509, 9], [510, 247], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 133, [['jsr', 4660], ['rts']]], [[[4660, 131, None], [0, 133, None]], [[388, 255], [389, 255]]])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| call and return | [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]] | [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]] | Passed |
| push and pull | [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 18]], [[510, 34], [511, 18]]] | [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 18]], [[510, 34], [511, 18]]] | Passed |
| stack pointer wraps below page start | [[[769, 0, None], [770, 0, None], [771, 0, None], [772, 1, 51]], [[256, 86], [257, 51]]] | [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 86]], [[256, 68], [257, 51], [511, 86]]] | Failed |
| pull wraps above page end | [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []] | [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []] | Passed |
| nested calls | [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2292, 255, None]], [[508, 2], [509, 9], [510, 243], [511, 8]]] | [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2292, 255, None]], [[508, 2], [509, 9], [510, 243], [511, 8]]] | Passed |
| return address carries into high byte | [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]] | [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]] | Passed |
| return from top of memory | [[[4660, 127, None], [0, 129, None]], [[384, 255], [385, 255]]] | [[[4660, 127, None], [0, 129, None]], [[384, 255], [385, 255]]] | Passed |
SHA-256 / 08313e3fb3c9eca740d438e5e6b41bde83add68027cc28be1336fec09adc880d
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
pc, sp, ops = args
mem = {}
trace = []
def push(v):
nonlocal sp
mem[0x100 + sp] = v & 0xFF
sp = (sp - 1) & 0x1FF
def pull():
nonlocal sp
sp = (sp + 1) & 0xFF
return mem.get(0x100 + sp, 0)
for op in ops:
got = None
if op[0] == 'jsr':
ret = (pc + 2) & 0xFFFF
push(ret >> 8)
push(ret)
pc = op[1]
elif op[0] == 'rts':
lo = pull()
hi = pull()
pc = ((hi << 8 | lo) + 1) & 0xFFFF
elif op[0] == 'pha':
push(op[1])
pc += 1
elif op[0] == 'pla':
got = pull()
pc += 1
else:
pc += 1
trace.append([pc, sp, got])
return [trace, [[k, mem[k]] for k in sorted(mem)]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 18], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 18]], [[510, 34], [511, 18]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 86], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 86]], [[256, 68], [257, 51], [511, 86]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2289, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2292, 255, None]], [[508, 2], [509, 9], [510, 243], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 129, [['jsr', 4660], ['rts']]], [[[4660, 127, None], [0, 129, None]], [[384, 255], [385, 255]]])], [('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 19], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 19]], [[510, 34], [511, 19]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 87], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 87]], [[256, 68], [257, 51], [511, 87]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2290, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2293, 255, None]], [[508, 2], [509, 9], [510, 244], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 130, [['jsr', 4660], ['rts']]], [[[4660, 128, None], [0, 130, None]], [[385, 255], [386, 255]]])], [('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 20], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 20]], [[510, 34], [511, 20]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 88], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 88]], [[256, 68], [257, 51], [511, 88]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2291, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2294, 255, None]], [[508, 2], [509, 9], [510, 245], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 131, [['jsr', 4660], ['rts']]], [[[4660, 129, None], [0, 131, None]], [[386, 255], [387, 255]]])], [('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 21], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 21]], [[510, 34], [511, 21]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 89], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 89]], [[256, 68], [257, 51], [511, 89]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2292, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2295, 255, None]], [[508, 2], [509, 9], [510, 246], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 132, [['jsr', 4660], ['rts']]], [[[4660, 130, None], [0, 132, None]], [[387, 255], [388, 255]]])], [('call and return', [1536, 253, [['jsr', 1792], ['nop'], ['rts']]], [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]]), ('push and pull', [512, 255, [['pha', 22], ['pha', 34], ['pla'], ['pla']]], [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 22]], [[510, 34], [511, 22]]]), ('stack pointer wraps below page start', [768, 1, [['pha', 51], ['pha', 68], ['pha', 90], ['pla']]], [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 90]], [[256, 68], [257, 51], [511, 90]]]), ('pull wraps above page end', [1024, 254, [['pla'], ['pla'], ['pla']]], [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []]), ('nested calls', [2293, 255, [['jsr', 2304], ['jsr', 2560], ['rts'], ['rts']]], [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2296, 255, None]], [[508, 2], [509, 9], [510, 247], [511, 8]]]), ('return address carries into high byte', [4350, 240, [['jsr', 8192], ['rts']]], [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]]), ('return from top of memory', [65533, 133, [['jsr', 4660], ['rts']]], [[[4660, 131, None], [0, 133, None]], [[388, 255], [389, 255]]])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| call and return | [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]] | [[[1792, 251, None], [1793, 251, None], [1539, 253, None]], [[508, 2], [509, 6]]] | Passed |
| push and pull | [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 18]], [[510, 34], [511, 18]]] | [[[513, 254, None], [514, 253, None], [515, 254, 34], [516, 255, 18]], [[510, 34], [511, 18]]] | Passed |
| stack pointer wraps below page start | [[[769, 0, None], [770, 511, None], [771, 510, None], [772, 255, 0]], [[256, 68], [257, 51], [767, 86]]] | [[[769, 0, None], [770, 255, None], [771, 254, None], [772, 255, 86]], [[256, 68], [257, 51], [511, 86]]] | Failed |
| pull wraps above page end | [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []] | [[[1025, 255, 0], [1026, 0, 0], [1027, 1, 0]], []] | Passed |
| nested calls | [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2292, 255, None]], [[508, 2], [509, 9], [510, 243], [511, 8]]] | [[[2304, 253, None], [2560, 251, None], [2307, 253, None], [2292, 255, None]], [[508, 2], [509, 9], [510, 243], [511, 8]]] | Passed |
| return address carries into high byte | [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]] | [[[8192, 238, None], [4353, 240, None]], [[495, 0], [496, 17]]] | Passed |
| return from top of memory | [[[4660, 127, None], [0, 129, None]], [[384, 255], [385, 255]]] | [[[4660, 127, None], [0, 129, None]], [[384, 255], [385, 255]]] | Passed |
SHA-256 / 2df64d6a8045402f64f17807c1d30dcf6755052aed1750afc082542f16c6d440
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 7 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗Verification & scope
A deterministic bounded teaching model of one emulator rule; the instruction semantics are a stipulated contract inspired by common ISAs and are not a claim of cycle-exact or architectural conformance. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:17.242992+00:00.
Case digest / fc077379c140e74f830aebf4a46c29ca5b4ac5a1b42924270828d3db6f156bb6