Listing: 07-system-test.asm
Related: Reset / entry
path · Error codes
Callers: cold boot @011F, continuous
menu [T] @01C7
High-level flow
CALL 01D2
│
├─ steal return addr + next word from caller stack
├─ SP := 6000h (test stack)
│
├─ CALL 01F7 PROM checksum 0000–1FFF
│ CF → fail
├─ CALL 0211 Keyboard loopback
│ CF → fail
├─ CALL 0244 Disk controller probe (if drives configured)
│ CF → fail
├─ CALL 026D Screen RAM + main memory banks
│ CF → fail
│ NC,NZ → user abort (ESC/space) during mem test
│
├─ on any CF from first three: CALL 03DD
├─ on CF from 026D: fall into CALL 03DD
│
├─ restore SP := 2200h
└─ JP (HL) back to caller (flags preserved: CF / NZ)
Does not print a banner itself — callers print first:
| Caller | Before CALL 01D2 |
On return |
|---|---|---|
Cold @011F |
PERFORMING SYSTEM TEST @06CF |
CF → menu 014F; NC →
store phase "02", continue auto-boot |
Menu T @01C7 |
PERFORMING CONTINUOUS SYSTEM TEST - CYCLE + hex
@5FDC |
CF → RET menu; NZ →
RET menu (abort); Z,NC → inc cycle,
loop |
Stack / return mechanism
(01D2–01F6)
01D2 POP HL ; return address (was pushed by CALL)
01D3 POP DE ; caller's next stack word
01D4 LD SP, 6000h ; dedicated test stack
01D7 PUSH DE / PUSH HL ; keep them across tests
… tests …
01F0 POP HL / POP DE
01F2 LD SP, 2200h ; menu / post-boot stack
01F5 PUSH DE
01F6 JP (HL) ; resume after CALL 01D2
Flags from the last test (and 03DD, which preserves AF)
reach the caller:
| Flags after suite | Meaning |
|---|---|
| CF=1 | A test failed (message already printed) |
| CF=0, Z=1 | All tests passed |
| CF=0, NZ=1 | User aborted memory test with ESC
(1Bh) or space (20h) |
03DD (OUT (00h),02) runs on failure paths
before return (console side-effect).
Test 1 — PROM checksum
@ 01F7
B = 0
for HL = 0000 … 1FFF:
B += (HL)
if B == 20h: RET Z ; pass (CF clear)
else:
print " FAULT IN PROM " @078B (entry via 0788)
SCF / RET ; fail
| Item | Detail |
|---|---|
| Region | Entire Executive image 0000–1FFF (8 KB
ROM) |
| Check | Sum of all bytes must equal 20h after
running total in B (SUB 20h / RET Z) |
| Fail string | FAULT IN PROM (078B,
print ptr 0788) |
| Pass | RET with Z, NC |
| Fail | SCF / RET |
Test 2 — Keyboard @ 0211
IN A,(00) ; dummy read
wait up to 65536 loops for IN A,(01) bit0 set
timeout → fail
OUT (00), 10h ; command / stimulus
wait for IN A,(01) bit1 (ready bit 02h)
timeout → fail
IN A,(00)
if A == AAh: RET Z ; pass
else fail
| Item | Detail |
|---|---|
| Ports | Data 00, status 01 (same as menu kbd) |
| Expect | Data byte AAh after
OUT (00),10h |
| Fail string | FAULT IN KEYBOARD (07A0,
print ptr 079D) |
| Pass | RET Z |
| Fail | print + SCF / RET |
Test 3 — Disk controller
@ 0244
if (09AA)==0 and (09AD)==0: RET Z ; no drives configured → skip pass
CALL 15AA ; controller probe
if A==0: RET Z ; probe OK
print " FAULT IN DISK CONTROLLER "
CALL 03F2 with A ; [status]
CALL 03F2 with B ; [detail]
print trailer @07F1
SCF / RET
| Item | Detail |
|---|---|
| Skip | Both ROM config (09AA) and (09AD) zero →
no disk test |
| Probe | Shared helper 15AA (same as
menu/auto-boot) |
| Fail string | FAULT IN DISK CONTROLLER
(07B9, print ptr 07B6) |
| Extra | Bracketed hex via 03F2:
[aa] [bb] then string @07F1 |
| Pass | RET Z (skip or probe OK) |
| Fail | print + SCF / RET |
This dump: (09AA)=C8h, (09AD)=07h →
disk test runs.
Test 4 — Screen + main memory
@ 026D
Largest test. Outline:
CALL 03DA ; kbd data read (flush?)
CALL 0321 ; screen RAM AA/55 @7000–77FF, bank CE
CF → fail already printed
size probe:
map D=FF, BF, 7F; write/read complement at 77FFh
(5FDA) = max working bank code (FF/BF/7F/3F)
(5FDB) = CEh
fill/verify loop over banks D=0 … (5FDA), skip D0–DF window:
CALL 0346 ; march test bank D
allow ESC/space abort → OR A / RET (NC, NZ)
verify loop: remap each bank, CP (77FF) against D
mismatch → BLOCK CONFLICT path
pass: RET
4a. Screen memory —
0321
map bank D=CEh via 0436
for HL=7000…77FF:
save C=(HL)
write AAh, verify; write 55h (CPL), verify
restore (HL)=C
pass RET; fail → " FAULT IN SCREEN MEMORY " @07D6, SCF
FAULT IN SCREEN MEMORY (07D6,
print ptr 07D3) |4b. Bank size discovery
(0274–02B1)
Tests write/read at 77FFh under mapper
values:
| D | Meaning if OK |
|---|---|
FFh |
largest config |
BFh |
mid |
7Fh |
smaller |
| else | (5FDA)=3Fh |
(5FDB) set to CEh
(screen/attr bank marker used as skip bound).
4c. Per-bank march —
0346 / 03AC
For each bank D (0 … max, skipping
D0–DFh):
03AC: AA/55 fill verify entire7000–77FF
- Write pattern
(L + H + (5FDC))to each byte (continuous-test cycle feeds entropy)
- Verify pattern
On data mismatch (0370):
print " FAULT IN MEMORY - BLOCK " @06FF/0702
print [bank D] via 03F2
print ", MASK " @071B
print [xor mask E]
print ", EVEN ADDRESS " or ", ODD ADDRESS " (@0722 / @0734) by bit0 of L
if bank D >= 40h:
SCF / RET ; soft fail back to suite
else:
print "MAIN MEMORY FAULT - HALTING" @0745
CALL 03DD / HALT ; ★ does not return
4d. Block conflict
(0306)
If verify pass stores at 77FF don’t match expected bank
id:
print " FAULT IN MEMORY - BLOCK CONFLICT " @0763/0766
print [expected D] [read E]
print trailer @07F1
SCF / RET
4e. User abort
(02BF–02CD)
During fill loop, if kbd status ready:
- ESC (
1Bh) or space (20h) →OR A/RET(NC, typically NZ)
- Continuous test treats NZ as stop → return to
menu
- Cold boot treats only CF as fail → abort may look
like “pass” and continue to phase
"02"/ auto-boot (flags NC)
Fault string from test suite
| String | Addr (approx) | Raised by |
|---|---|---|
FAULT IN PROM |
078B |
01F7 |
FAULT IN KEYBOARD |
07A0 |
0211 |
FAULT IN DISK CONTROLLER |
07B9 |
0244 |
FAULT IN SCREEN MEMORY |
07D6 |
0321 |
FAULT IN MEMORY - BLOCK |
0702 |
0346 fail |
, MASK |
071B |
0346 |
, EVEN ADDRESS |
0722 |
0346 (even L) |
, ODD ADDRESS |
0734 |
0346 (odd L) |
MAIN MEMORY FAULT - HALTING |
0745 |
0346 if bank < 40h |
FAULT IN MEMORY - BLOCK CONFLICT |
0766 |
026D verify |
Related banners (callers, not from test suite):
| String | Addr | When |
|---|---|---|
PERFORMING SYSTEM TEST |
06CF |
Cold boot once |
PERFORMING CONTINUOUS SYSTEM TEST - CYCLE |
06A4 |
Menu T each cycle |
Continuous test mode — menu
[T] @ 01B2
01B2 (5FDC)=0 ; cycle counter
loop:
01B6 print @06A4
print hex (5FDC) + CR
CALL 01D2
RET C ; fail → menu (014F on stack)
RET NZ ; abort → menu
INC (5FDC)
JR loop ; pass → next cycle
(5FDC) also feeds the memory pattern in
0346 so each cycle stresses different data.
Cold boot integration
@ 011F
store phase (5FD8)="01"
print PERFORMING SYSTEM TEST
CALL 01D2
JP C, 014F ; fail → main menu
store phase (5FD8)="02" ; pass → may auto-boot next
fall into 012B path
If phase already "01" or "02", cold path
skips the suite (see entry path doc).
Helpers used
| Addr | Role |
|---|---|
03E4 |
Print bit-7 string |
03F2 |
Print [xx] hex byte |
0406/0413 |
Hex digits |
0443 |
Putchar |
03D5/03DA |
Kbd status/data |
03DD |
OUT (00),02 on fail |
0436 |
Map bank OUT (16),~D |
15AA |
Disk controller probe |
Memory window under test
Banked window 7000h–77FFh
(2 KB) via mapper port 16h. Screen bank
CEh. Main banks discovered among
FF/BF/7F/3F.
Attribute banks D0–DF skipped
in the march loop (video attrs from cold boot).
Pass / fail summary for callers
┌─ PROM fail ────────────── CF ──┐
CALL 01D2 ──────┼─ KBD fail ─────────────── CF ──┤
├─ DISK fail ────────────── CF ──┤
├─ MEM/SCRN fail ────────── CF ──┤── JP (HL) to caller
├─ MEM HALT (bank<40h) ─── never returns
├─ user ESC/space ─────── NC,NZ ─┤
└─ all OK ──────────────── NC,Z ─┘
| Caller | CF | NZ (abort) | Z,NC (pass) |
|---|---|---|---|
| Cold boot | → menu | continues (treated as pass) | phase "02", auto-boot path |
| Continuous T | → menu | → menu | next cycle |
Annotated outline
01D2 re-stack to SP=6000; run 01F7,0211,0244,026D
fail any → 03DD; always JP (HL) with flags
01F7 sum ROM[0..1FFF]==20h else FAULT IN PROM
0211 kbd OUT 10h, expect AAh else FAULT IN KEYBOARD
0244 if drives: 15AA else skip; fail → FAULT IN DISK CONTROLLER [a][b]
026D screen 0321; size probe; for each bank 0346; verify; ESC/space abort
0321 bank CE, AA/55 7000-77FF else FAULT IN SCREEN MEMORY
0346 bank D march; fail detail or MAIN MEMORY FAULT HALT
03AC AA/55 pretest for 0346