Skip to content

162B OutString

In progress   MON 162B (114 decimal) · Mnemonic OUTST · Group: File Operations (manual section 2.4)

Available from: All programs (manual compatibility box)

Emulation source: src/handlers/mon_162B_OutString.c

Description

Writes a string of characters to a peripheral file, e.g., a terminal or a printer.

  • You cannot use this monitor call for mass-storage files.
  • The output buffer of the device may be too small. Then the program waits until the required buffer space becomes available.
  • Parameters are fetched and returned through the alternative page table.
  • The maximum string length is 2048 bytes (as in OutputString).
  • For performance reasons, it is inadvisable to use this call from the ND-500(0). Use OutputString instead.
  • Appendix F contains an ASCII table.

Parameters

Name Type Direction Description
DeviceNo INTEGER2 In Logical device number. See appendix B. You cannot use 1 for your own terminal. Use ExecutionInfo to get its logical device number instead. File numbers are illegal.
TextWrite STRING In Character string to be output (max 2048 bytes).

Direction: In = the program supplies the value, Out = the call returns it, In/Out = both.

See also

OutMessage, OutUpTo8Bytes, Out8Bytes, OutputString, OutNumber, OutByte, and InString

Compatibility

Machines Users Programs
ND-100 and 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
Yes Yes Yes Yes No

Examples

From the manual (OCR text, not corrected).

INTEGER : DeviceNo, NoOfBytes, ReturnStatus
BYTES : TextWrite(0:79)
...
Monitor_Call('OutString', DeviceNo, TextWrite, NoOfBytes, ReturnStatus)
INTEGER DeviceNo, NoOfBytes, RetStatus
CHARACTER TextWrite*80
...
Monitor_Call('OutString', DeviceNo, TextWrite(1:80), NoOfBytes, RetStatus)
DeviceNo, NoOfBytes, ReturnStatus : INTEGER2;
TextWrite : PACKED ARRAY [0..79] OF CHAR;
...
OutString(DeviceNo, TextWrite, NoOfBytes, ReturnStatus);
01 DevNo COMP.
01 NoOfBytes COMP.
01 RetStatus COMP.
01 TextWrite PIC X(100).
...
MONITOR-CALL "OutString" USING DevNo, TextWrite, NoOfBytes, RetStatus.
DeviceNo : W BLOCK 1
TextWrite : STRINGDATA 'This is a text...'
ReturnStatus : W BLOCK 1
OutString : EQU 37B9 + 162B
...
CALLG OutString, 2, DeviceNo, TextWrite
IF K GO Error
W1 := ReturnStatus      % Status is returned in W1
...
Error, ...
register.
LOA (PAR         % Load register A with address of parameter list.
MON 162          % Monitor call OutString.
STA STAT         % Store status returned.
...
STAT, 0
PAR, DEVNO       % Logical device number.
TEXT             % String to be written.
COUNT            % Number of characters to be written.
...

DEVNO, ...
TEXT, 'THIS IS A TEST'
COUNT, 16        % Write 14 characters.

ndmonlib implementation

In progress Registered MON_STATUS_IN_PROGRESS: partly implemented. The dispatcher calls the handler.

Handler mon_162B_OutString
Code lines 82 (non-blank, non-comment lines in the file)

Notes from the handler source

src/handlers/mon_162B_OutString.c line 36

Output-string control bytes (carve 162B-OutString OUTST loop, byte-verified):
  047B (0x27, apostrophe ') = STRING TERMINATOR - stop output here.
  044B (0x24, dollar '$')   = emit '$' then a line feed (012B).
The ND LINKER calls OUTST in a 2-ARG, terminator-driven form (DeviceNo, Text)
with NO byte count; our old code required a 3-arg count form and errored,
so the linker's banner/prompt never appeared. Accept 2 or 3+ args: an
explicit NoOfBytes (arg2) caps the length, and the 0x27 terminator always
stops output.

src/handlers/mon_162B_OutString.c line 59

NoOfBytes is optional (3-arg form only); the 0x27 terminator bounds the
2-arg form. Always cap at MAX_OUTSTRING_LENGTH for safety.

src/handlers/mon_162B_OutString.c line 86

File numbers are illegal for this call; other devices route to the
console (this is a peripheral/terminal output call).

src/handlers/mon_162B_OutString.c line 95

String-source resolution:
 - 2-arg form (the LINKER): arg1 is the address of an ND-500 STRING
   DESCRIPTOR {element_count@+0, base_address@+4} (big-endian words), the
   same layout SCOMP/SCOPA use. Output element_count bytes from base.
 - 3+-arg form: arg1 is the raw character address, bounded by NoOfBytes.
Both still honour the 0x27 terminator. (Verified: the linker's arg1
0xB0056B34 = {count=0xC8, base=0xB0056A6C}; the raw bytes there are the
descriptor, not text.)

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_162B_OutString.c
Last updated 2026-07-17

Parameter notes

1. TextWrite

Field Value
Note THE ARGUMENT COUNT SELECTS THE STRING CONVENTION - this is the single most important fact about emulating 162B. In the 2-ARG form (DeviceNo, TextWrite) the argument is the address of an ND-500 STRING DESCRIPTOR {element_count @ +0, base_address @ +4}, big-endian words - the same layout SCOMP/SCOPA use. In the 3+-ARG form it is the RAW character address, bounded by NoOfBytes. Both forms honour the 0x27 terminator.
Verified Yes

2. NoOfBytes

Field Value
Note OPTIONAL. This YAML's own parameters list has only DeviceNo and TextWrite - it agrees with the linker's 2-arg usage. nd500x accepts 2 or 3+ args and caps every form at 2048 bytes.
Verified Yes

3. ReturnStatus

Field Value
Note Only written when 4 or more CALLG args are present: 0 on success, 52 on the file-number rejection. Not exercised by any observed caller.
Verified No

Observed calls

1. ND linker (linker-b01.dom), banner/prompt output

Field Value
Params Deviceno: terminal
Textwrite: 0xB0056B34 -> descriptor
Expectation The linker calls OUTST in the 2-ARG, terminator-driven form with NO byte count. nd500x previously REQUIRED the 3-arg count form and returned error 111 (157B Missing parameter), so the linker's banner and prompt NEVER APPEARED - it looked like the linker was silent/hung when in fact its output call was being rejected.
Note Byte-verified that arg1 is a descriptor and not text: the raw bytes at 0xB0056B34 are {0x000000C8, 0xB0056A6C}, and the readable string lives at the base address. Commit fc3ac5b.

Return contract

  • Success: K flag cleared; ReturnStatus = 0 if a 4th arg is present.
  • Errors

    Code Octal Meaning
    124 174B Illegal parameter (a file number was passed - the manual says file numbers are illegal)
    111 157B Missing parameter (fewer than 2 CALLG args)

Verified

1. 047B (0x27, apostrophe) is the STRING TERMINATOR - output stops there and the 0x27 is not emitted.

Field Value
Evidence Carve 162B-OutString, the OUTST loop, byte-verified. Carve folder: NDInsight/tools/sintran-segment-carver/versions/L-VSX-500/re/mon-analysis/162B-OutString/

2. 044B (0x24, dollar) emits '$' AND THEN A LINE FEED (012B). It is a formatting control byte, not an ordinary character.

Field Value
Evidence Carve 162B-OutString, OUTST loop at 41043-41052 (octal).

3. The 2-arg descriptor decode is right: with it the linker produces its banner and startup dialogue.

Field Value
Evidence Commit fc3ac5b: "162B OUTST: treat the 2-arg form as a string descriptor {count, base} and honor the 0x27 terminator and 0x24 line-feed convention." With this plus 511B/143B the linker TALKS.

Unverified

  • The 0x27 terminator and the 0x24 line-feed rule are carved from the ND-100 OUTST worker. Whether the ND-500 path applies BOTH identically is not separately proven; the linker's observed strings exercise the descriptor decode and the terminator, and no traced string has contained a 0x24.
  • ReturnStatus value 52 on the file-number rejection is NOT a real SINTRAN code in the Appendix A sense (52 is "No such friend"); it is a leftover. The K-flag error correctly returns 124 (174B). Treat the 52 as an nd500x artefact, not a contract.
  • The manual's "the program waits until the required buffer space becomes available" is not modelled - nd500x never blocks on output.
  • The manual's "Parameters are fetched and returned through the alternative page table" is not modelled as such; nd500x reads them through the normal path.
  • A DEBUG PROBE REMAINS IN THE HANDLER, gated behind the environment variable ND500X_OUTST_DUMP - it dumps arg1 as raw/descriptor/via-base. Harmless when unset.

Discrepancies

1. The manual says of DeviceNo: "You cannot use 1 for your own terminal. Use ExecutionInfo to get its logical device number instead."

Field Value
Is nd500x does NOT enforce this - it accepts device 1 and routes any non-file device to the console. No observed caller passes 1, so the rule is neither exercised nor disproven; the emulator is simply more permissive than the manual. Recorded so nobody reads the permissiveness as a documented fact.
Evidence nd500x/src/libmon/handlers/mon_162B_OutString.c - only is_mass_storage_file() is rejected; there is no device == 1 check.

Sources

Doc Note
SINTRAN III Monitor Calls (ND-860228.2 EN) The manual body of this YAML.
NDInsight/tools/sintran-segment-carver/versions/L-VSX-500/re/mon-analysis/162B-OutString/ The OUTST loop carve - source of the 0x27 terminator and the 0x24 line-feed rule.

Source

SINTRAN III Monitor Calls (ND-860228.2 EN), page 385.