MON 162B (octal) - OutString (OUTST)¶
CORRECTED 2026-07-15 (byte-verified). The worker + dispatch described below are on the DEBUNKED model and are WRONG. Byte truth from the carved L07 image:
MCTAB[162B] = 006002B = 3OUTS=112671Bin segment 025-S3IRPIT, reached by the real dispatchMON 162B -> ENT14(072167B) -> GOTAB[162B]=MFELL(072114B) -> CALLP(032201B) -> MCTAB[162B]=3OUTS. Any "GOTAB from commoncode" / "uncarved CALLPROC bridge" / old worker name below is an artefact of the wrong table. Verified:dd if=044-S3IDPIT.bin bs=1 skip=2052 count=2->95 b9. Cross-ref ../317B-ExecuteCommand/README.md and SINTRAN/CARVING-HANDOFF.md sec 3a.
Writes a string of characters to a peripheral file (e.g. a terminal or a printer). It cannot be used for mass-storage files. If the device output buffer is too small the program waits until buffer space becomes available. The maximum string length is 2048 bytes.
Status: GOTAB dispatch head byte-proven as fall-through (GOTAB[162B] =
000000, no per-call stub); the OUTST worker body is real SINTRAN L bytes and
loops the GETCH (get character) and SOUTB (output byte) primitives; the exact
MON 162 -> worker link crosses an uncarved kernel bridge (see
Honest caveats). All addresses/values are octal.
- Full disassembly:
162B-OutString.ASM- the actual code (the OUTST worker body; there is no entry stub because the GOTAB slot is zero). - Bytes live once in the canonical segment layer:
../../segments-ref/.
Dispatch path¶
flowchart LR
A["User program<br/>MON 162B"] --> B["ENT14 level-14<br/>T = MON number"]
B --> C["GOTAB[162B] = 000000<br/>(byte-proven: fall-through)"]
C -.uncarved MFELL / CALLPROC.-> E["OUTST out-string worker<br/>006-S3FS :41013B"]
E --> F["GETCH get char :30062B<br/>SOUTB output byte :31030B"]
class A blue
class B,C blue
class E,F green
classDef blue fill:#E3F2FD,stroke:#0D47A1,color:#0D47A1
classDef teal fill:#E0F7FA,stroke:#00838F,color:#00838F
classDef green fill:#E8F5E9,stroke:#2E7D32,color:#2E7D32
The GOTAB slot is zero, so there is no per-call entry stub. The dashed hop
(C -> E) is the resident MFELL/CALLPROC fall-through second-level dispatch -
it is not present in any carved segment, so it is the one link that cannot be
followed statically.
Code location (dispatch path)¶
Every row is a real region you can open. Byte offset = (addr - loadbase) in octal words x 2
(equal to the decimal byteoff column of the segment .hex).
| Role | Segment (full disasm) | Addr range (octal) | Byte offset | Symbol | Verdict |
|---|---|---|---|---|---|
| GOTAB[162] dispatch word | commoncode.asm - .hex | 071415B (1 word) |
58906 | GOTAB+162 = 000000 |
VERIFIED (fall-through) |
| resident MFELL/CALLPROC bridge | - (uncarved) | - | - | CALLPROC |
UNVERIFIED |
| OUTST worker body | 006-S3FS.asm - .hex | 41013B-41021B + loop 41030B-41061B |
11286 | OUTST |
real bytes; link MISATTRIBUTED |
| GETCH get-character primitive | 006-S3FS.asm - .hex | 30062B (call target) |
2148 | GETCH |
called by OUTST (link cell 41065) - VERIFIED |
| SOUTB output-byte primitive | 006-S3FS.asm - .hex | 31030B (call target) |
3120 | SOUTB |
called by OUTST (link cell 41067) - VERIFIED |
Verify by hand: grep '^41013 ' ../../segments-ref/006-S3FS/006-S3FS.hex -> byte offset 11286;
then dd if=../../../segments/006-S3FS.bin bs=1 skip=11286 count=8 | od -An -tx1 -> 22 27 cc 65 cc 59 f0 07
(each pair is one 16-bit word, big-endian on disk = octal 021047 146145 146131 170007 = STD I 47 / RADD CLD SL DA / RADD CLD SB DD / SAB 7, the OUTST entry).
The GOTAB slot itself:
dd if=../../../resident/SINTRAN-DATA_commoncode.bin bs=1 skip=58906 count=2 | od -An -tx1 -> 00 00 (= 000000, fall-through).
Instruction walkthrough¶
Full listing: 162B-OutString.ASM. The functional body is
the OUTST worker; there is no F16xx stub because GOTAB[162] = 0. All calls to
shared workers are indirect (JPL I / JMP I) through the pointer-word table
at 41062-41070; those words are data (link cells), not code, and their
resolved worker addresses are annotated in the .ASM.
Entry prologue (41013-41021) - 41013 STD I 47 stashes the caller's
double-word parameter (through link cell 41064); 41016 SAB 7 builds the
7-word local frame B; 41017 JPL I 44 -> 003752 is the shared resident
prologue worker; 41020 LDA I 44 loads the working value; 41021 JMP 7 ->
41030 joins the shared output loop.
Output loop (41030-41057) - 41032 LDT ,B 1 / 41033 AAT -1 decrement the
remaining count; 41034 SKP IF DT GRE SD / 41035 JMP 23 -> 41060 exits when
the count is exhausted. 41037 JPL I 26 -> 030062 (GETCH) fetches the next
character; 41041 SKP IF DA UEQ ST / 41042 JMP 16 -> 41060 exits on the
terminator. The character is emitted by 41050/41052/41055 JPL I -> 031030
(SOUTB, output one byte to the device); a special character path
(41051 SAA 12) emits an extra byte. 41056 RADD AD1 / 41057 JMP -25 ->
41032 loops back to the next character.
Exit (41060-41061) - 41060 SAA -7 unwinds the 7-word frame (matching
SAB 7), then 41061 JMP I 7 -> 003776 returns through the resident return
cell. The output loop and the link-cell table are shared with the sibling entry
SRTOU (41022B), whose own entry body (41022-41027) is not part of
MON 162B.
The JPL I calls to GETCH (030062, link cell 41065) and SOUTB
(031030, link cell 41067) are the byte-level proof that OUTST is the OutString
worker: it fetches characters and writes them one byte at a time to the device -
exactly "write a string of characters to a peripheral file".
Parameter / register contract¶
| Reg / field | Dir | Meaning | Verdict |
|---|---|---|---|
| entry point | in | 41013B = OUTST worker entry (fall-through, no stub) |
VERIFIED (bytes) |
A (manual) |
in | address of the parameter list { DeviceNo, TextWrite, NoOfBytes } |
inferred (manual MAC example) |
D (double) |
in | caller parameter block, saved first (STD I 47) |
VERIFIED (copy); layout inferred |
B+1 |
internal | remaining character count (loop guard, LDT ,B 1 / AAT -1) |
VERIFIED (bytes); label inferred |
B+6 |
internal | current character/argument (STA ,B 6) |
VERIFIED (bytes) |
local frame B |
internal | SAB 7 = 7-word working frame |
VERIFIED (bytes) |
B+2 |
out | returned status word (resident return slot) | inferred (manual; store not in this window) |
The user-visible parameter-list layout (DeviceNo, TextWrite, NoOfBytes)
lives in the caller-side MON 162 wrapper and the uncarved MFELL/CALLPROC
frame, so the precise field assignment is inferred from the manual, not
byte-proven here.
Pseudo-code (for an emulator)¶
See 162B-OutString.pseudo.c - a pseudo-C model of
the handler for emulator authors. Control flow + the GETCH -> SOUTB output loop
are byte-verified; the parameter-field semantics are inferred from the call
structure and the manual. Every ND-100 instruction in the model is translated
per the canonical
ND100-INSTRUCTION-SEMANTICS.md.
Honest caveats¶
What is byte-proven: GOTAB[162B] = 000000 (level-14 dispatch, a fall-through
with no per-call vector); the OUTST worker body at 41013B in 006-S3FS is
real code (entry bytes 021047 146145 146131 170007 match the disassembly); and
it belongs to the character-output family - it loops GETCH (030062B, link cell
41065) and SOUTB (031030B, link cell 41067), the get-character and
output-byte primitives.
What is NOT proven: the link from the zero GOTAB slot to the OUTST worker.
Because the vector is zero there is no stub to disassemble and no pointer to
dereference; dispatch drops into the resident MFELL/CALLPROC second-level
path, which lives in an uncarved overlay. So the MON 162 -> OUTST
attribution rests on the OUTST symbol name + its GETCH/SOUTB output loop +
the matching behaviour, not a followed pointer - hence MISATTRIBUTED in the
strict sense. Confirming the link needs a live trace: issue a real MON 162,
single-step the level-14 fall-through into the resident CALLPROC dispatch, and
confirm P lands on OUTST = 41013.
Shared code: OUTST (41013B) and the sibling entry SRTOU (41022B) share
the output loop (41030-41061) and the link-cell table (41062-41070). Only the
OUTST entry body (41013-41021) plus the shared loop are MON 162B; the SRTOU
entry body is a sibling and is not documented here.
The link cells 003752 (resident prologue) and 003776 (resident return) match
no FILSYS-SYMBOLS entry; their low addresses suggest resident-monitor /
save-restore routines outside the file-system segment and are not resolved here.
Method: ../../../../../EXTRACTING-RESIDENT-CODE.md - dispatch reality: ../../TASK-05-mismatches.md - master map: ../../MON-CALL-INDEX.md.