Skip to content

12B SetCommandBuffer

Validated   MON 12B (10 decimal) · Mnemonic SETCM · Group: Input and Output Monitor Calls (manual section 2.5)

Available from: Background programs (manual compatibility box)

Emulation source: src/handlers/mon_12B_SetCommandBuffer.c

Description

Transfers a string to the command buffer. The command buffer contains the last command input from the terminal. You may read the command buffer by reading from logical device number 0. See InByte.

  • The command @TERMINAL-STATISTICS lists the command buffer.
  • You may apply the SINTRAN III command editing characters to the command buffer when the program has terminated.
  • The parameter is fetched through the alternative page table.
  • You may use this monitor call to erase sensitive information in the command buffer, e.g., password parameters.

Notes

  • Version history: M-version increased the maximum length of the command buffer from 104 characters to 150 characters (ND-860230-7A-EN SINTRAN III - Release Information - M-Version.md:1075).

Parameters

Name Type Direction Description
Command STRING In String to transfer to the command buffer (up to 32 characters).

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

See also

ExecuteCommand, CallCommand

Compatibility

Machines Users Programs
ND-100 and ND-500 All users Background 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).

BYTES : Command(0:31)
...
Monitor_Call('SetCommandBuffer', Command)
    CHARACTER Command*32
    ...
    Monitor_Call('SetCommandBuffer', Command(1:32))
    Command : PACKED ARRAY [0..31] OF CHAR;
    ...
    SetCommandBuffer(Command);
    01 Command PIC X(32).
    ...
    MONITOR-CALL "SetCommandBuffer" USING Command.
Command : STRINGDATA 'CLOSE-FILE 102'
SetCommandBuffer : EQU 37B9 + 12B
...
CALLG SetCommandBuffer, 1, Command
| Instruction | Operand | Description                                           |
|-------------|---------|-------------------------------------------------------|
| LDA         | (CMND)  | %Address of string with command.                      |
| MON         | 12      | %Monitor call SetCommandBuffer.                       |
| ...         |         |                                                       |
| CMND,       | 'CLOSE-FILE 102' | %Transfer 'CLOSE-FILE 102' to the command buffer. |

ndmonlib implementation

Validated Registered MON_STATUS_VALIDATED in src/core/mon_registry.c: implemented, tested and working.

Handler mon_12B_SetCommandBuffer
Code lines 21 (non-blank, non-comment lines in the file)

Notes from the handler source

src/handlers/mon_12B_SetCommandBuffer.c line 35

Read command string. Like 317B UECOM, the VDM front-ends (NC etc.) pass a
[Length:4][Pointer:4] descriptor (arg0 = {maxlen, ptr, ...}; text at the
pointer, 0x27-terminated), not an inline string. Try the descriptor form
first, fall back to the direct read.

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

Note

Implemented and proven against NC. The hard-won fact here is the ARGUMENT LAYOUT: the VDM front-ends do not pass an inline string.

Parameter notes

1. Command

Field Value
Note THE DESCRIPTOR. NC (and the other VDM front-ends) pass the command as a [Length:4][Pointer:4] DESCRIPTOR, not as inline text: arg0 points at {maxlen, ptr, ...} and the actual text lives AT the pointer, terminated by 0x27 ("'"). Exactly the same layout as 317B UECOM. A direct string read of arg0 reads the descriptor struct itself, whose first byte is 0x00, and yields "". nd500x tries mon_read_descriptor_string() first and falls back to the inline read for callers that really do pass text inline.
Verified Yes

2. Command

Field Value
Note The command buffer is device 0. A program reads it back with 1B INBT on logical device number 0. nd500x stores it via the shared mon_set_command_buffer() in mon_file_table.c - the SAME buffer a device-0 read drains.
Verified Yes

3. Command

Field Value
Note THREAD SAFETY: the shared command-buffer functions in mon_file_table.c keep static global state with no mutex. External synchronisation is required for multi-threaded access.
Verified Yes

Observed calls

Caller Params Expectation Note
NC C front-end (nc-a06.dom) Command: 'CC -> B' NC sets a compiler status label into the command buffer. Before the descriptor fix the emulator decoded this as the empty string. Commit b615586: "NC's SETCM now decodes as 'CC -> B' (a compiler status label) instead of ''. NC unchanged: clean MON 0B LEAVE at instr 1902382."

Return contract

  • Success: K flag cleared; the command buffer now holds the string.
  • Errors

    Code Octal Meaning
    111 157B Missing parameter (fewer than 1 argument supplied)

Verified

1. MON 12B dispatches via MCTAB to the L07 worker SETOL.

Field Value
Evidence Carve L-VSX-500 12B-SetCommandBuffer/README.md CORRECTED 2026-07-15: MCTAB[12B] slot 005632B (segment 044-S3IDPIT, byte offset 1844) = 050666B = SETOL in segment 003-S3CP. Reproduced: dd if=044-S3IDPIT.bin bs=1 skip=1844 count=2 -> 51 b6.

2. The command buffer read back from device 0 is CR-terminated, never raw EOF.

Field Value
Evidence Commit 19f7354, byte-proven in the L07 command processor by a carve trace: at the 47B source marker it substitutes CR (050773: SAA 15 -> SBYT) and resets the byte pointer. So 47B is an INTERNAL SOURCE MARKER that never reaches a device-0 reader: the buffer a program reads via 1B INBT ends in CR (015B / 0x0D), never 47B, never raw EOF. A program launched with no arguments still reads a lone CR. Read-side confirmation: the ND linker's first device-0 read returns 0x0D and it proceeds to its banner.

3. Getting the device-0 termination wrong makes a real program busy-spin.

Field Value
Evidence Before 19f7354, mon_read_command_buffer_char() returned raw -1 (EOF) once the stored bytes ran out; the ND linker then busy-spun - measured 20,088 consecutive 1B INBT retries at PC=0xB004E759 in 600k instructions.

Unverified

  • WHAT A DEVICE-0 READ RETURNS AFTER THE CR (past end-of-line) is still unproven - the linker never does it. nd500x treats it as a suspend (STOP_WAIT_INPUT). Explicitly flagged as unproven in commit 19f7354.
  • The 32-CHARACTER CAP the manual documents is NOT enforced by nd500x - the handler takes up to 256 bytes. Recorded as a pending correction for BOTH emulators in nd500x/docs/MON_CSHARP_SYNC_HANDOFF.md PART C: "12B SETCM: cap the stored command buffer at 32 chars (documented capacity)."
  • The SETOL worker body was not decoded, so the real truncation/padding behaviour at the 32-char boundary is unknown.
  • The carve found NO ND-100 code worker for this call: the short name SETCM resolves only in the L07 N500-SYMBOLS list (SETCM=106214B, the ND-500 companion), and CBUF=170207B - the command-buffer DATA area - is zero-filled in this L image.
  • Not yet audited against the carve - listed under "NOT yet audited vs carve" in nd500x/docs/HANDOFF_MON_COMPLETENESS.md.

Discrepancies

1. Earlier carve version: "GOTAB[12B] = 000000, a fall-through; there is no ND-100 code worker" on the disproven GOTAB-is-the-MON-table model. The body of that README still reads that way below its own correction header.

Field Value
Is MCTAB[12B] = 050666B = SETOL, byte-proven; the real dispatch is MON 12B -> ENT14(072167B) -> GOTAB[12B]=MFELL(072114B) -> CALLP(032201B) -> MCTAB[12B]=SETOL.
Evidence Carve CORRECTED 2026-07-15 header; dd if=044-S3IDPIT.bin bs=1 skip=1844 count=2 -> 51 b6.

Sources

Doc Note
NDInsight/tools/sintran-segment-carver/versions/L-VSX-500/re/mon-analysis/12B-SetCommandBuffer/README.md MCTAB[12B] = SETOL. Note the README body contradicts its own correction header.
nd500x/docs/CAT500_UECOM_CSHARP_HANDOFF.md The [len][ptr] descriptor layout shared with 317B UECOM (the CAT-500 route).

Source

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