Skip to content

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 &nbsp;&nbsp;&nbsp;&nbsp;%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.