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.