Files
8086-Programs/interrupts/scripts/check.py
T
asmhatreandClaude Sonnet 5.5 09af523f8c Add interrupts module: INT 3 (CC breakpoint) vs INT 21h (DOS services)
NASM sources, DOSBox/FreeDOS Debug/Unicorn harness, captured output and 31
assertions backing the ankurm.com article "INT 3 vs INT 21h in 8086 Assembly".

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KqJyCidz3ZgRyHABv2GVJh
2026-09-30 19:10:56 +00:00

62 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""Assertions that pin every claim the article makes about the captured output."""
import pathlib, re, sys
OUT = pathlib.Path(__file__).resolve().parent.parent / "output"
fails = []
def rd(n): return (OUT / n).read_text()
def check(name, cond):
print(("PASS " if cond else "FAIL ") + name)
if not cond: fails.append(name)
lst = rd("01-opcodes.lst")
check("int3 assembles to the single byte CC", re.search(r" CC\s+int3", lst) is not None)
check("NASM 'int 3' assembles to CD 03", re.search(r" CD03\s+int 3", lst) is not None)
check("int 21h assembles to CD 21", re.search(r" CD21\s+int 21h", lst) is not None)
check("into assembles to CE", re.search(r" CE\s+into", lst) is not None)
t = rd("02-hello21.txt")
check("hello21 prints its string", "Hello from INT 21h, AH=09h" in t)
check("AH=4Ch return code 7 visible as ERRORLEVEL", "ERRORLEVEL is at least 7" in t)
t = rd("03-fn-tour.txt")
check("AH=30h reports a version", re.search(r"AH=30h DOS version\s+: \d+\.\d+", t) is not None)
check("AH=2Ah/2Ch ranges ok", "okok" not in t and re.search(r"ranges : ok ok", t) is not None)
check("AH=02h+06h write AB", re.search(r"AH=06h\s+: AB", t) is not None)
check("AH=01h returned 5A ('Z') and AH=0Ah counted 5 chars 'Ankur'", "AH=01h got 0x5A ; AH=0Ah count = 5, text = Ankur" in t)
check("AH=25h/35h round trip", re.search(r"vector 60h\s+: ok", t) is not None)
check("AH=48h/49h alloc+free ok", re.search(r"alloc\+free 4 KB\s+: ok", t) is not None)
check("AH=48h 1 MB request fails CF=1 AX=0008", "(fails) : CF=1 AX=0008" in t)
check("file I/O: 12 bytes read, LSEEK says 12", "12 bytes read ; LSEEK(end) says size = 12" in t)
check("findfirst sees U.TXT size 12", "U.TXT size = 12" in t)
check("reopening deleted file: CF=1 AX=0002", "CF=1 AX=0002" in t)
check("mkdir/rmdir ok", "mkdir+rmdir : ok" in t)
check("child exit code 7, termination type 0 via AH=4Dh", "AH=4Dh return code = 7 type = 0" in t)
t = rd("04-int3-handler.txt")
check("CC: return IP = trap + 1", "CC (INT3): return IP = trap address + 1" in t)
check("CD 03: return IP = trap + 2", "CD 03 (INT 3): return IP = trap address + 2" in t)
check("IF and TF are 0 inside the handler, IF back to 1 after IRET",
t.count("IF in handler = 0, TF in handler = 0, IF after IRET = 1") == 2)
check("IF pushed on the stack was 1", t.count("IF pushed = 1") == 2)
t = rd("05-int3-default.txt")
check("INT 3 with no handler: program survives under DOSBox", "after INT3 (program survived)" in t)
if (OUT / "06-debug-cc.txt").exists():
t = rd("06-debug-cc.txt")
check("DEBUG + CC: 'Unexpected breakpoint interrupt' and IP=0104", "Unexpected breakpoint interrupt" in t and "IP=0104" in t)
check("DEBUG + CC: next instruction after trap is MOV AX,2222", "0104 B82222 MOV AX,2222" in t)
check("DEBUG + CC: single-step then AX=2222", "AX=2222" in t)
t = rd("07-debug-cd03.txt")
check("DEBUG + CD 03: no breakpoint message", "Unexpected breakpoint interrupt" not in t)
check("DEBUG + CD 03: stops at IP=0104 inside the INT 03 instruction", "IP=0104" in t and "03B82222 ADD DI,[BX+SI+2222]" in t)
check("DEBUG + CD 03: MOV AX,2222 never runs (AX stays 1111 after stepping)", "AX=2222" not in t)
else:
print("SKIP DEBUG checks (run scripts/fetch-debug.sh first)")
t = rd("08-bp-experiment.txt")
check("Unicorn: CC patch trap return IP = site+1, resume gives CX=3", "CC patch=CC trap: vector=3 return IP=7C03 (site=7C02, +1)" in t and "CX=3 (expected 3)" in t)
check("Unicorn: CD 03 patch trap return IP = site+2 and resume goes wrong", "return IP=7C04 (site=7C02, +2)" in t and "CX=0 (expected 3)" in t)
sys.exit(1 if fails else 0)