Skip to content

MON 513B (octal) — XMSGCallB (B5XMS)

The buffer-carrying entry into the ND-500 → ND-100 XMSG gateway. It decodes the XMSG function number from the ND-500 message buffer, demuxes through a jump table to the right subfunction, calls shared resident XMSG workers, and issues the underlying MON 200B (XMSG) on behalf of the ND-500 process. It shares one code body byte-for-byte with MON 512B (A5XMS); both symbols resolve to the same entry 142253B.

Status: handler body is real SINTRAN L bytes (carved, control-flow closed); the entry 142253B = B5XMS is L07-symbol-proven; the level-12 GOSW dispatch that reaches it and the shared XMSG workers it calls live in an uncarved resident overlay (see Honest caveats). All addresses/values are octal.

  • Full disassembly: 513B-XMSGCallB.ASM — the actual code, one region (the level-12 handler body, entry + jump table + tails).
  • Bytes live once in the canonical segment layer: ../../segments-ref/.

Dispatch path

MON 513B is an ND-500 level-12 call (call number 513B ≥ 0400): it is not dispatched through the ND-100 GOTAB. The GOTAB[513] word lands on T108R, a 1-word filler stub, and must not be presented as the handler.

flowchart LR
    A["ND-500 process<br/>MON 513B"] --> B["stop MOCALL, level-12<br/>MCHANDEL reads MCNO=513B"]
    B -.uncarved GOSW.-> C["5CMNO / L12MIN<br/>GOSW index 11"]
    C --> D["B5XMS handler body<br/>026-S3IMPIT :142253B"]
    D --> E["MON 200B (XMSG)<br/>+ shared resident workers"]
    class A blue
    class B,C teal
    class D,E 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 dashed hop (B ⇢ C) is the resident level-12 GOSW dispatch (5CMNO/L12MIN, index 11) — it is not present in any carved segment, so it is inferred, not followed statically.


Code location (dispatch path)

Every carved row is a real region you can open. Byte offset = (addr − loadbase) in octal words × 2.

Role Segment (full disasm) Addr range (octal) Byte offset Symbol Verdict
GOTAB[513] slot (NOT this call path) commoncode.asm · .hex word at 071746B (1 word) 59340 T108R filler = 057557B MISATTRIBUTED
Level-12 GOSW dispatch (5CMNO index 11) — (uncarved resident image) — — 5CMNO / L12MIN UNVERIFIED (inferred)
Handler body (shared with 512B) 026-S3IMPIT.asm · .hex 142253B–142611B (223w) 74070 B5XMS = A5XMS = 142253B VERIFIED
Shared XMSG workers (via pointer words 142433–142437, 142631+) — (uncarved resident image) — — resident XMSG workers UNVERIFIED

Handler byte offset: (142253B − 32000B) = 110253B = 37035 dec, × 2 = 74070.

Verify by hand: grep '^142253 ' ../../segments-ref/026-S3IMPIT/026-S3IMPIT.hex → byte offset 74070; then dd if=../../../segments/026-S3IMPIT.bin bs=1 skip=74070 count=8 | od -An -tx1 → cc 7b 52 57 f7 41 c6 c0 (= octal 146173 051127 173501 143300, the B5XMS entry — matches the local 513B-XMSGCallB.bin head, sha256 fc9553472ab54c6d28302488b1e6a8bc79d5023e62f2d57d55cde26b8d2a82c1).


Instruction walkthrough

Full listing: 513B-XMSGCallB.ASM. Addresses octal.

Entry / prologue (142253–142263) — loads a pointer via LDT I 127, indexes with AAX 101 + LDATX to fetch a field from the ND-500 message/PIT block, masks it (AND 125), then computes AAA -57 and SKP IF 0 GRE SA. If the value is out of the low range it jumps to the generic tail at 142420 (JMP 135).

Range/validity check (142264–142271) — re-indexes (AAX -131, LDATX), JAF 26 to the dispatch decoder at 142314; else SKP IF DA UEQ SD and JMP I 114 → 142405 (error/return path).

First XMSG issue (142272–142302) — builds arguments (AAX 140, LDATX, SAT 43, RADD CLD 0 DL) and executes MON 200 at 142277 — the underlying XMSG monitor call. On return JMP I 105 → 142405; a second guard SKP IF DT GRE 0 selects success (142303) vs. error (JMP I 104 → 142406).

Function dispatch table (142314–142402) — at 142314 it re-reads the message function field (LDT I 66, AAX 101, LDATX, AAX -101, AND 63), forms an index with RADD SA DP, then falls into a dense jump table (142324–142402) of ~55 entries. Most slots funnel to a small set of shared tails: 142420 (generic), 142445, 142454, and the pointer-indirect handlers 142410/142411/142412 (SBYT data words used as JMP-I targets), 142413/142414 → 142555, 142415 → 142567, 142416 → 142574. This is the per-XMSG-subfunction demux (LFREA/LFWRI/LFWRT and siblings).

Shared worker calls via pointers (142420–142453) — the 142420 block sets up (SAA -22, SAD SHR 20, SAT 1) and calls shared workers through indirect JPL I using the pointer words at 142433–142437. Those pointer words are DATA (addresses of common XMSG worker routines living elsewhere in the resident image), not executable here. 142445 loads a buffer descriptor chain (AAX 104, LDDTX/LDATX/LDXTX) and joins the exit at 142611.

Result marshalling (142454–142610) — the 142504–142535 block does the heavier work: strings of STATX/STZTX/LDDTX/STDTX build/copy the return descriptor and call out via JPL I 103 → 142640/142641 and JMP I 103 → 142642 (more resident-worker pointers). Several near-identical tails (142545, 142555, 142562, 142567, 142574, 142604) each reload a descriptor at a different offset and converge on 142611. The 142454 and 142574 tails include an error branch SAA -36 / JMP I → 142631 (negative error code −36 = XMSG error return).

Exit (142611+) — LDT I 24 … restores context and returns to the level-12 dispatcher; the return/skip is via saved pointer words at 142631/142633/142640, just past the carved-for-closure window edge.

Plain language: fetch XMSG function code from the ND-500 message block → validate/range-check → demux through the jump table to the correct subfunction → call shared resident XMSG worker(s) via indirect pointers → issue MON 200B (XMSG) and/or copy the data buffer → marshal the result/error code back into the message block → return to the level-12 gateway.


Parameter / register contract

Inputs (ND-500 message-buffer / PIT fields):

Reg / field Dir Meaning Verdict
XMSG function number (LDT I 127 + AAX 101, later AND 63) in selects the XMSG subfunction VERIFIED (decoded at 142253–142322)
data buffer descriptor (AAX 104 chains) in buffer for LFREA/LFWRI/LFWRT VERIFIED (loaded at 142445/142504)
MON 200B argument block (SAT 43/SAT 42, LDA 76) in passed to underlying XMSG VERIFIED (built before MON 200 at 142277/142312)

Outputs:

Reg / field Dir Meaning Verdict
result descriptor written back into msg block (STATX/STDTX) out per-subfunction results VERIFIED (142504–142535, tails)
error code −36 (SAA -36) out XMSG error return VERIFIED (142462, 142602)
success vs. error path (SKP IF DT GRE 0) out branch on MON 200 T-register status VERIFIED (142301)
skip return out control returns to the level-12 GOSW via saved pointer words (142631+) inferred

The exact field-offset names (+101, +104, +130, +131 …) are indexes into the message/PIT base register; the L07 table does not resolve these numeric literals to symbolic field names inside the carved window, so their names are UNVERIFIED.


Pseudo-code (for an emulator)

See 513B-XMSGCallB.pseudo.c — a pseudo-C model of the handler for emulator authors, translated line-by-line against the canonical ../../instruction-semantics/ND100-INSTRUCTION-SEMANTICS.md. Every LDATX/LDXTX/LDDTX/STATX/STZTX/STDTX is modelled as a 24-bit PHYSICAL, MMU-bypassing access phys[EL] with EL = ((T & 0xFF) << 16) | ((X + disp3) & 0xFFFF) — T is the message-buffer bank, X the physical word cursor (reference §5); RADD CLD is a register COPY and RADD SA DP is the computed jump P = P + A (reference §3). The control flow, the function-field decode, the jump table, and the two MON 200B issue points are byte-verified; the MON 200B skip-return convention, the out-of-carve worker/return pointers (142433–142437, 142631+), and the per-subfunction semantics are marked UNVERIFIED / inferred from the call structure.


Honest caveats

What is byte-proven: the handler body at 142253B–142611B is real SINTRAN L code, carved from 026-S3IMPIT (load 32000B) and control-flow closed (0 direct branches escape the file). The entry symbol B5XMS = 142253B is confirmed by the L07 symbol table, and the first entry word 146173B matches the carved .bin head (cc 7b). A5XMS and B5XMS both equal 142253B, so MON 512B and MON 513B share one body and split on the message function field, not on a separate entry.

What is NOT proven — reconciling prove-mon.py: prove-mon.py 513 inspects the ND-100 GOTAB, which is not the path this call uses. It reports GOTAB[513] = 057557B landing on T108R, a 1-word filler stub. That is the expected signature of a slot that is not a real GOTAB handler: MON 513B is an ND-500 level-12 call dispatched via the level-12 GOSW (5CMNO/L12MIN, index 11), which lives in an uncarved resident overlay. Anyone reading only prove-mon would wrongly conclude the handler is a 1-word stub. The real handler is B5XMS = 142253B, proven by the L07 symbol table plus the carved byte anchors — hence the GOTAB row above is marked MISATTRIBUTED and the GOSW dispatch row UNVERIFIED.

Also unproven: the shared XMSG worker routines reached through pointer words 142433–142437 and 142631+ live outside the carved window; the exact skip-return contract to the level-12 dispatcher was not disassembled; and the numeric message-field offsets were not resolved to L07 symbolic names.

One naming note: this README cites 026-S3IMPIT.bin while prove-mon names the overlay 025-S3IRPIT.bin — these are the Image vs. Save copy of the same resident S3MPIT segment (load 32000B); the byte window is identical.

Method: ../../../../../EXTRACTING-RESIDENT-CODE.md §7.6/7.7 · dispatch reality: ../../TASK-05-mismatches.md · master map: ../../MON-CALL-INDEX.md.