MON 241B (octal) - NewUser (SUSCN)¶
Switches the user name you are logged in under (like logging out and logging in as another user); your program continues under the new user name. Restore the old name with OldUser (MON 242B). From the ND-100 you may execute NewUser more than once without OldUser between. User RT and user SYSTEM only; background programs.
Status: GOTAB dispatch head byte-proven as fall-through (GOTAB[241B] =
000000, no per-call stub); the SUSCN worker body is real SINTRAN L bytes in the
file-system segment 006-S3FS (a FILSYS-SYMBOLS symbol). The worker is real
executable code with user-name validation, a user-RT test, a save/restore of the
old name words, an install call and four error tails (the code region ends at 106527B, bounded by
the next symbol RUSCN=106562B). The
exact MON 241 -> worker link crosses an uncarved kernel bridge (see
Honest caveats). All addresses/values are octal.
- Full disassembly:
241B-NewUser.ASM- the actual code (the SUSCN 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 241B"] --> B["ENT14 level-14<br/>T = MON number"]
B --> C["GOTAB[241B] = 000000<br/>(byte-proven: fall-through)"]
C -.uncarved MFELL / CALLPROC.-> E["SUSCN switch-user worker<br/>006-S3FS :106377B"]
E --> F["validate name; save old name;<br/>install new user; return status"]
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; for 006-S3FS (load base 26000B) it is (addr - 26000B) x 2.
| Role | Segment (full disasm) | Addr range (octal) | Byte offset | Symbol | Verdict |
|---|---|---|---|---|---|
| GOTAB[241] dispatch word | commoncode.asm - .hex | 071474B (1 word) |
59000 | GOTAB+241 = 000000 |
VERIFIED (fall-through) |
| resident MFELL/CALLPROC bridge | - (uncarved) | - | - | MFELL/CALLPROC |
UNVERIFIED |
| SUSCN worker body | 006-S3FS.asm - .hex | 106377B-106527B (code) + 106530B (pad) + 106531B-106561B (link cells) |
49662 | SUSCN |
real bytes = CODE; body link MISATTRIBUTED |
The window is bounded strictly by the next symbol RUSCN=106562B (115 words).
Words 106377B-106527B are code, 106530B is a one-word ROP NOOP pad, and
106531B-106561B are a pointer table (link cells) the JPL I / JMP I
indirections dereference - they are data.
Verify by hand: grep '^106377 ' ../../segments-ref/006-S3FS/006-S3FS.hex
-> byte offset 49662; then
dd if=../../../segments/006-S3FS.bin bs=1 skip=49662 count=2 2>/dev/null | od -An -tx1
-> 22 59 (the stored word = octal 021131, a genuine STD I 131
instruction, the SUSCN entry). The GOTAB slot itself:
grep '^71474 ' ../../segments-ref/SINTRAN-DATA_commoncode/SINTRAN-DATA_commoncode.hex
-> 71474 000000 000 000 59000; then
dd if=../../../resident/SINTRAN-DATA_commoncode.bin bs=1 skip=59000 count=2 2>/dev/null | od -An -tx1
-> 00 00 (= 000000, fall-through). prove-mon.py 241 reads the same GOTAB zero.
Instruction walkthrough¶
Full listing: 241B-NewUser.ASM. The body is the SUSCN worker
(there is no F16xx stub because GOTAB[241] = 0). SUSCN (Switch USer, Change Name)
sits directly before its twin RUSCN (OldUser, MON 242B).
Prologue (106377-106403) - 106377 STD I 131 saves the incoming A/D pair,
106400-106401 copy the return link and frame pointer, 106402 SAB 32 and
106403 JPL I 126 -> [106531] call the resident prologue worker.
Name validation (106404-106445) - 106412 JPL I 123 -> [106535] validates the
new user-name string; 106420 JPL I 117 -> [106537] processes the project password;
106426-106431 pack/store the coded name (SHA ZIN 10 = logical left shift 8,
ADD I = add); the BSKP/JAF tests branch to the error tail with code 25.
User-RT test + install (106445-106507) - 106445-106450 SAT 1 / SKP IF DA EQL
ST is the user-RT branch; when not user RT the resident workers at [106550] and
[106551] do the extra check; 106464-106467 save the current (old) name words
into B+30/B+31; 106476 JPL I 56 -> [106554] installs the new user; 106500
stores the returned status; 106505 MIN ,B 4 + 106507 JMP I 50 -> [106557] is the
success return.
Restore-on-failure (106510-106527) - the install-failure tail (106512-106521)
restores the saved old-name words before returning the error code; the other tails
converge on 106506 SAA -32 / the indirect return.
Parameter / register contract¶
Manual-side names/types are from 241B_NewUser.yaml.
| Reg / field | Dir | Meaning | Verdict |
|---|---|---|---|
X (UserName) |
in | address of the new user-name string (MAC LDX (USER) |
inferred (manual) |
A (UserPassword) |
in | user password coded as an integer (MAC LDA (PASSW) |
inferred (manual) |
T (ProjectPassword) |
in | address of the project-password string (MAC LDT (PROJP) |
inferred (manual) |
B+30 / B+31 |
internal | saved old name words for restore-on-failure (STA ,B 30/31, LDA ,B 30/31) |
VERIFIED (bytes); meaning inferred |
A (UserType) |
out | status: public users 0, user SYSTEM 1, user RT 2 (STA ,B 2) |
inferred (manual) |
| error return | out | standard error code in A (106506 SAA -32, tail code 25) |
VERIFIED (bytes); code value inferred |
Pseudo-code (for an emulator)¶
See 241B-NewUser.pseudo.c - a pseudo-C model for
emulator authors. The control flow (name validation, the user-RT test, the
save/restore of the old name, the install call and the four error tails) is
byte-verified; the register/field semantics and the exact name/password packing are
inferred from the manual and the code shape.
Every instruction in the pseudo-code is translated against the canonical
ND-100 instruction semantics reference
(RADD CLD copy idiom, RADD SB DA/DX register add, SHA ZIN 10 logical left
shift, SKP IF DA EQL ST compare, JAF flag branch, MIN ,B increment and skip,
JPL I/JMP I indirect call/return, addressing-mode effective addresses).
Honest caveats¶
What is byte-proven: GOTAB[241B] = 000000 (level-14 fall-through;
prove-mon.py 241 reads commoncode file byte 0xe678 = 00 00); the SUSCN worker
body at 106377B in 006-S3FS is real code (first word 021131B = STD I 131
matches the disassembly); and it is a switch-user routine (name validation, old-name
save/restore, install call, status return), consistent with NewUser.
Which segment and why: SUSCN=106377B is a FILSYS-SYMBOLS symbol, so it lives
in the file-system segment 006-S3FS, directly before its OldUser twin
RUSCN=106562B. The window 106377B-106561B is bounded strictly by RUSCN (115
words): 106377-106527 are code, 106530 is a ROP NOOP pad, and 106531-106561
are the JPL I/JMP I link-cell table.
What is NOT proven: the link from the zero GOTAB slot to the SUSCN 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 - hence MISATTRIBUTED in the strict
sense: the attribution rests on the SUSCN symbol name + matching behaviour + the
RUSCN twin, not a followed pointer. The JPL I/JMP I link cells
(106531..106561) are a pointer table whose runtime targets are not resolved here.
Confirming the dispatch link needs a live trace of a real MON 241.
Method: ../../../../../EXTRACTING-RESIDENT-CODE.md - dispatch reality: ../../TASK-05-mismatches.md - master map: ../../MON-CALL-INDEX.md.