412B FileAsSegment¶
Validated MON 412B (266 decimal) · Mnemonic FSCNT · Group: File System Operations (manual section 2.9)
Available from: All programs (manual compatibility box)
Emulation source: src/handlers/mon_412B_FileAsSegment.c
Description¶
Connects a file as a segment to your domain. You can then access the file as a logical segment. This reduces the access time.
- The file must be open. The access must be specified in the OpenFile call.
- The file is disconnected when it is closed.
- A file may be connected to several processes simultaneously. It is your responsibility to synchronize simultaneous accesses.
- You may not use ReadFromFile (mon 117) or WriteToFile (mon 120) on a file which is connected to a segment. Refer to these monitor calls for further details.
Parameters¶
| Name | Type | Direction | Description |
|---|---|---|---|
FileNo |
INTEGER2 | In | File number. See OpenFile. |
LogSegmentNo |
INTEGER2 | In | Logical segment number in the domain. The segment number must be free. Use 0 to select the first free segment. |
AccessType |
INTEGER2 | In | Access type: 0=file contains initial data, 1=uninitialized empty file, 2=primarily sequential access, 3=combination of 1 and 2. |
SegmentNo |
INTEGER2 | Out | Logical segment number selected (returned if LogSegmentNo was 0). |
Direction: In = the program supplies the value, Out = the call returns it, In/Out = both.
See also¶
FileNotAsSegment which disconnects the file
Compatibility¶
| Machines | Users | Programs |
|---|---|---|
| ND-500 | All users | All programs |
The manual's compatibility box for this call, word for word.
Yes/no fields from the YAML extraction (not in the manual's words):
| ND-100 | ND-500 | User programs | RT programs | System programs |
|---|---|---|---|---|
| No | Yes | No | No | No |
Examples¶
From the manual (OCR text, not corrected).
INTEGER FileNo, LogSegmentNo, Type, SegmentNo
...
Monitor_Call('FileAsSegment', FileNo, LogSegmentNo, Type, SegmentNo)
IF (ErrCode .NE. 0) THEN ...
FileNo, LogSegmentNo, Type, SegmentNo : LONGINT;
...
FileAsSegment(FileNo, LogSegmentNo, Type, SegmentNo);
IF ErrCode <> 0 THEN ...
01 FileNo COMP.
01 LogSegmentNo COMP.
01 Type COMP.
01 SegNo COMP.
01 ErrCode COMP.
...
MONITOR-CALL "FileAsSegment" USING FileNo, LogSegmentNo, Type, SegNo.
CALL "CbError" USING ErrCode.
IF ErrCode NOT = 0 GO ...
FileNo : W BLOCK 1
LogSegmentNo : W BLOCK 1
Type : W BLOCK 1
SegmentNo : W BLOCK 1
ErrCode : W BLOCK 1
FileAsSegment : EQU 37B9 + 412B
...
CALLG FileAsSegment, 4, FileNo, LogSegmentNo, Type, SegmentNo
IF K GO ERROR
...
ERROR : W1 =: ErrCode %ErrorCode in W1 register.
ndmonlib implementation¶
Validated Registered MON_STATUS_VALIDATED in src/core/mon_registry.c: implemented, tested and working.
| Handler | mon_412B_FileAsSegment |
| Code lines | 72 (non-blank, non-comment lines in the file) |
Notes from the handler source¶
src/handlers/mon_412B_FileAsSegment.c line 64
Validate access type. Per the YAML/carve, AccessType is
0 = file contains initial data, 1 = uninitialized/empty,
2 = primarily sequential, 3 = combination of 1 and 2.
(NOT read/write/rdwr - the read/write capability comes from the file's
OPEN mode, below.)
src/handlers/mon_412B_FileAsSegment.c line 91
Capability access mode comes from the FILE'S OPEN MODE, not AccessType.
Read-only open modes -> RO segment; everything else -> RW.
src/handlers/mon_412B_FileAsSegment.c line 125
Return the assigned segment number to the CALLER'S OUTPUT PARAMETER (arg 3).
This is how callers learn which segment the file landed on, and therefore
which address to read it at. Verified against CAT-500 (cat-cat5-b06.dom):
its wrapper issues
call MON 412B, $0x4, b.0x14, b.0x18, b.0x1C, @b.0x20
i.e. a 4th, indirect OUT argument. Without this write the caller keeps the
cell's stale value (0), addresses segment 0, reads zeros instead of the
mapped file, and then fails - and its later 413B FSCDNT(LogSegmentNo=0)
mismatches the real segment too.
Emulation research¶
Source
This section comes from the emulation: block of the call's YAML file in the NDInsight repo. It records what was learned while implementing the call in nd500x; its status is nd500x's, not ndmonlib's.
| Status (nd500x) | verified |
| nd500x handler | nd500x/src/libmon/handlers/mon_412B_FileAsSegment.c |
| Last updated | 2026-07-17 |
Supporting code¶
nd500x/src/cpu/nd500_segment_alloc.c
Parameter notes¶
1. SegmentNo
| Field | Value |
|---|---|
| Note | THE OUT-PARAMETER RULE. The assigned segment number MUST be written into the caller's arg-3 slot. This is the single most expensive defect class in this codebase: a handler that computes the right value, leaves it only in W1, and never writes the caller's cell. The caller then keeps that cell's STALE value (typically 0), addresses segment 0, and reads zeros. nd500x writes arg 3 AND leaves the value in W1, because some callers read the register instead. |
| Verified | Yes |
2. AccessType
| Field | Value |
|---|---|
| Note | AccessType selects INITIAL CONTENT, not permissions: 0 = file contains initial data, 1 = uninitialized/empty, 2 = primarily sequential, 3 = combination of 1 and 2 - exactly as the manual field in this YAML says. The segment's READ/WRITE capability comes from the FILE'S OPEN MODE (50B AccessCode), NOT from this parameter. |
| Verified | Yes |
3. all INTEGER parameters
| Field | Value |
|---|---|
| Note | On ND-500 all four are 32-bit words. |
| Verified | Yes |
Observed calls¶
1. CAT-500 (cat-cat5-b06.dom), wrapper @0x0801F080 / @0x0801F08B, 4 call sites
| Field | Value |
|---|---|
| Params | Fileno: b.0x14 Logsegmentno: b.0x18 Accesstype: b.0x1C Segmentno: @b.0x20 (INDIRECT - an OUT pointer) |
| Expectation | The exact call is "call MON 412B, $0x4, b.0x14, b.0x18, b.0x1C, @b.0x20" - four arguments, the fourth indirect. CAT-500 does NOT read its CAT intermediate with 117B RFILE; it CONNECTS the scratch file as a segment and reads it with ordinary MEMORY LOADS from that logical segment. It takes the segment number from the OUT slot to know which address to read. |
| Note | With the OUT parameter unwritten, all of this was byte-observed: CAT-500 read 0 from the cell, addressed segment 0 (67 reads at vaddr 0x00000000), never once read the real mapping at 0x20000000 (0 reads across the whole code-generation window of 11102 reads), failed with "ERROR can't generate code" WITHOUT EVER READING ITS INPUT, and its later 413B FSCDNT(LogSegmentNo=0) mismatched the real segment. With the OUT parameter written, CAT-500 reports "code generation : ok" and emits a real object file. |
2. ND linker (linker-b01.dom)
| Field | Value |
|---|---|
| Params | |
| Expectation | Static analysis of linker-b01.dom counts 14 call sites for 412B. Their runtime argument values have NOT been traced. |
Return contract¶
- Success: K flag cleared; the assigned segment number written to SegmentNo (arg 3) AND left in W1; the file's bytes mapped into an MMU/PST-backed logical segment in the caller's (CED) domain.
-
Errors
Code Octal Meaning 87 127B File number out of range 90 132B No file opened with this number 111 157B Missing parameter (fewer than 3 args) 124 174B Illegal parameter (AccessType > 3; file already mapped as a segment; the host-side connect failed)
Verified¶
1. 412B must return the segment number through the OUT PARAMETER, not only through W1.
| Field | Value |
|---|---|
| Evidence | Byte-observed against CAT-500 (cat-cat5-b06.dom) - see observed_calls. End to end after the fix: NC compiles B.C (" no errors detected ") -> SCRATCH-00001:CAT -> CAT-500 generate-code -> B:NRF = 513 bytes, whose header (0a 00 01 70 44 ...) matches the golden ND-produced reference ND-archive/500/FraTor/test-real/test-real.nrf, with proper NRF symbol records (PROG!NAME, V!ARGC, X). Commit 73ac594. |
2. AccessType is 0..3 and means initial-content, not permissions.
| Field | Value |
|---|---|
| Evidence | The manual field in this YAML and the carve pseudo.c agree. The handler had wrongly implemented 0=read/1=write/2=rdwr and REJECTED 3; corrected in commit fc3ac5b. Capability access is derived from the file's open mode (ACCESS_SEQ_READ / ACCESS_RAND_READ / ACCESS_RAND_READ_CTG -> read-only, else read-write). |
3. The mapping is real: the file's bytes are readable through the MMU.
| Field | Value |
|---|---|
| Evidence | nd500x/test/diag_fscnt.c maps ND-archive/500/FraTor/test-real/test-real.nrf with AccessType 0, enables the data MMU, and reads back the mapped logical segment via nd500_mmu_peek - the first 32 bytes MATCH the file (0A 00 01 70 44 00 ...). |
4. The routing of MON 412B in SINTRAN is byte-proven.
| Field | Value |
|---|---|
| Evidence | Carve: ND-500 System Monitor call via the S3SM5 0x60 vector table, slot 0x0274 -> body at 030-S3SM5.bin offset 0x98dd. MON dispatch is via MCTAB @ 005620B indexed by N. |
Unverified¶
- The carved BODY is NOT usable as a contract source. The body entry 0x98dd is SHARED with MON 127B and the disassembly past the entry loads is MISALIGNED; the carve's own pseudo.c states "body semantics, argument-slot mapping, and status/error contract are UNVERIFIED". The carve confirms ROUTING and EXISTENCE only. Our argument/error contract therefore comes from the manual plus CAT-500's observed usage.
- nd500x loads the ENTIRE file into the segment up front - it is NOT demand-paged. Fine for the small CAT scratch; wrong for very large files.
- The manual's "A file may be connected to several processes simultaneously" is not modelled: nd500x rejects a second connect of the same file with 174B.
- There is no WRITE-BACK from the segment to the file at any point in 412B's lifetime, and 413B does not do it either (see 413B). A file mapped writable and modified through the segment will not have those changes reach disk.
- The linker's 14 call sites' runtime arguments have not been traced.
Discrepancies¶
1. Emulator defect (fixed): AccessType treated as 0=read / 1=write / 2=rdwr, with 3 REJECTED as illegal.
| Field | Value |
|---|---|
| Is | AccessType is 0=initial-data, 1=uninitialized/empty, 2=primarily sequential, 3=combination of 1 and 2. The manual said so all along. |
| Evidence | Manual field + carve pseudo.c; corrected in commit fc3ac5b. |
2. Emulator defect (fixed): the assigned segment number was returned only in W1 via set_error_code, and the caller's OUT slot was never written.
| Field | Value |
|---|---|
| Is | The OUT slot (arg 3) MUST be written. THIS BUG CLASS RECURS - the same shape was later found in 511B DVIO (arg 15, the returned-count OUT parameter, "written by nobody, read straight after the call") and in 412B FSCNT before it. When a caller "fails without ever reading its input", suspect an unwritten OUT parameter FIRST. |
| Evidence | Commit 73ac594 (412B) and commit 2d9b00f (511B, which explicitly names "the MON 412B FSCNT bug shape"). |
3. The failure this bug produced looked like a code-generator defect ("ERROR can't generate code").
| Field | Value |
|---|---|
| Is | The code generator was fine; it had never been given its input. A symptom appearing far from the cause is characteristic of this bug class. |
| Evidence | Commit 73ac594. |
Sources¶
1. SINTRAN III Monitor Calls (ND-860228.2 EN)
| Field | Value |
|---|---|
| Page | 193 |
| Note | The manual page this YAML was extracted from. |
2. NDInsight/tools/sintran-segment-carver/versions/L-VSX-500/re/mon-analysis/412B-FileAsSegment/
| Field | Value |
|---|---|
| Note | Routing byte-proven; BODY semantics/args/errors explicitly UNVERIFIED by the carve itself (entry shared with MON 127B, disassembly misaligned). |
3. nd500x/docs/HANDOFF_412B_FSCNT_FileAsSegment.md
| Field | Value |
|---|---|
| Note | Full implementation handoff, incl. the ND-500 memory-management/isolation model. |
4. ND-05.009.4 EN ND-500 Reference Manual
| Field | Value |
|---|---|
| Note | Sections around lines 851, 939-945, 1237-1262 - logical segments, domains, capabilities, PST. "Connect a file as a segment" = install a capability in the CALLING domain's DATA capability table. |
5. 73ac594 (nd500x) - 412B must return the segment number via its OUT parameter
| Field | Value |
|---|---|
6. fc3ac5b (nd500x) - AccessType 0..3 + real MMU-backed segment connection
| Field | Value |
|---|---|
Source¶
SINTRAN III Monitor Calls (ND-860228.2 EN), page 193.