BASIC-DOS provides a subset of the PC DOS 2.x function interface, through INT 21h, with the function number in AH. Unless noted otherwise, functions that can fail return with carry set and an error code in AX, and with carry clear on success. Programs can also use the CP/M-style CALL 5 interface.
Functions not listed below (including any function above 56h) aren’t implemented, and return with carry set and AX = ERR_INVALID.
The DOS_* names are defined in dosapi.inc.
| AH | Name | Inputs | Outputs |
|---|---|---|---|
| 01h | DOS_TTY_ECHO | AL = character read from CON and echoed; checks CTRL-C | |
| 02h | DOS_TTY_WRITE | DL = character | Writes DL to CON; checks CTRL-C |
| 03h | DOS_AUX_READ | AL = character read from AUX | |
| 04h | DOS_AUX_WRITE | DL = character | Writes DL to AUX |
| 05h | DOS_PRN_WRITE | DL = character | Writes DL to PRN |
| 06h | DOS_TTY_IO | DL = character, or FFh to read | If DL = FFh: ZF clear and AL = character if one is available; no CTRL-C checks |
| 07h | DOS_TTY_IN | AL = character read from CON; no CTRL-C checks | |
| 08h | DOS_TTY_READ | AL = character read from CON; checks CTRL-C | |
| 09h | DOS_TTY_PRINT | DS:DX -> $-terminated string |
|
| 0Ah | DOS_TTY_INPUT | DS:DX -> input buffer (first byte = maximum characters, including the RETURN) | Second byte = # characters read (excluding the RETURN), followed by the characters |
| 0Bh | DOS_TTY_STATUS | AL = FFh if a character is available, 0 if not | |
| 0Ch | DOS_TTY_FLUSH | AL = function to invoke afterward (01h, 06h, 07h, 08h, or 0Ah) | Same as the function invoked |
The line editing keys that 0Ah supports are described in Typing Commands.
| AH | Name | Inputs | Outputs |
|---|---|---|---|
| 0Dh | DOS_DSK_RESET | Writes all modified disk buffers | |
| 0Eh | DOS_DSK_SETDRV | DL = drive # (0 = A:) | AL = # of drives; carry set if DL is invalid |
| 19h | DOS_DSK_GETDRV | AL = current drive # | |
| 1Ah | DOS_DSK_SETDTA | DS:DX -> DTA | |
| 2Fh | DOS_DSK_GETDTA | ES:BX -> DTA | |
| 36h | DOS_DSK_GETINFO | DL = drive # (0 = default, 1 = A:) | AX = sectors per cluster (FFFFh if invalid), BX = available clusters, CX = bytes per sector, DX = clusters per disk |
| 41h | DOS_DSK_DELETE | DS:DX -> filename | |
| 4Eh | DOS_DSK_FFIRST | CX = attributes, DS:DX -> filespec | DTA filled in (see FFB) |
| 4Fh | DOS_DSK_FNEXT | DTA from the previous 4Eh or 4Fh | DTA filled in |
| 56h | DOS_DSK_RENAME | DS:DX -> existing filename, ES:DI -> new filename |
| AH | Name | Inputs | Outputs |
|---|---|---|---|
| 3Ch | DOS_HDL_CREATE | CX = attributes, DS:DX -> filename | AX = handle |
| 3Dh | DOS_HDL_OPEN | AL = mode (see MODE_*), DS:DX -> filename | AX = handle |
| 3Eh | DOS_HDL_CLOSE | BX = handle | |
| 3Fh | DOS_HDL_READ | BX = handle, CX = byte count, DS:DX -> buffer | AX = bytes read |
| 40h | DOS_HDL_WRITE | BX = handle, CX = byte count, DS:DX -> buffer | AX = bytes written |
| 42h | DOS_HDL_SEEK | AL = method (0 = beginning, 1 = current, 2 = end), BX = handle, CX:DX = distance | DX:AX = new position |
| 44h | DOS_HDL_IOCTL | AL = IOCTL code, BX = handle, CX and DX = IOCTL data, DS:SI -> optional IOCTL data | DX = result |
Handles 0-4 are the predefined handles STDIN, STDOUT, STDERR, STDAUX, and STDPRN. Filenames can also be device names (eg, CON, NUL, or COM1), optionally followed by a colon and device-specific parameters (eg, CON:40,25).
For IOCTL code 00h (IOCTL_GETDATA), DOS returns DX = 80h for a device, or the file’s drive # (0-based) for a file. All other IOCTL codes are passed to the device driver as a DDC_IOCTLIN request; see IOCTL Functions for the BASIC-DOS-specific codes.
| AH | Name | Inputs | Outputs |
|---|---|---|---|
| 0Fh | DOS_FCB_OPEN | DS:DX -> unopened FCB | AL = 0 if found (FCB filled in), FFh if not |
| 10h | DOS_FCB_CLOSE | DS:DX -> FCB | AL = 0 if found, FFh if not |
| 14h | DOS_FCB_SREAD | DS:DX -> FCB | AL = FCBERR_* result; record read into the DTA |
| 21h | DOS_FCB_RREAD | DS:DX -> FCB | AL = FCBERR_* result; record FCBF_RELREC read into the DTA |
| 24h | DOS_FCB_SETREL | DS:DX -> FCB | Sets FCBF_RELREC from FCB_CURBLK and FCBF_CURREC |
| 27h | DOS_FCB_RBREAD | CX = # records, DS:DX -> FCB | AL = FCBERR_* result, CX = # records read |
| 29h | DOS_FCB_PARSE | AL = parse flags, DS:SI -> filespec, ES:DI -> FCB buffer | AL = 0 (no wildcards), 1 (wildcards), or FFh (invalid drive); DS:SI -> next character |
FCB support is read-only: FCB create, write, delete, and rename functions aren’t implemented yet.
| AH | Name | Inputs | Outputs |
|---|---|---|---|
| 48h | DOS_MEM_ALLOC | AL = block type (MCBTYPE_*, optionally with MCBTYPE_HIGH), BX = paragraphs | AX = segment; on failure, BX = largest available |
| 49h | DOS_MEM_FREE | ES = segment | |
| 4Ah | DOS_MEM_REALLOC | ES = segment, BX = new size in paragraphs | On failure, BX = largest available |
| AH | Name | Inputs | Outputs |
|---|---|---|---|
| 00h | DOS_PSP_TERM | Terminates the program (same as INT 20h) | |
| 26h | DOS_PSP_COPY | DX = segment | Creates a PSP by copying the current PSP |
| 4B00h | DOS_PSP_EXEC | DS:DX -> program name, ES:BX -> EPB | Loads and runs the program |
| 4B01h | DOS_PSP_EXEC1 | DS:DX -> program name, ES:BX -> EPB | Loads the program without starting it; EPB_INIT_SP and EPB_INIT_IP are filled in |
| 4B02h | DOS_PSP_EXEC2 | ES:BX -> EPB from DOS_PSP_EXEC1 | Starts the program loaded by DOS_PSP_EXEC1 (BASIC-DOS only) |
| 4Ch | DOS_PSP_RETURN | AL = exit code | Terminates the program |
| 4Dh | DOS_PSP_RETCODE | AL = exit code, AH = exit type (see Exit Types) | |
| 50h | DOS_PSP_SET | BX = PSP segment | Sets the current PSP |
| 51h | DOS_PSP_GET | BX = current PSP segment | |
| 55h | DOS_PSP_CREATE | DX = segment | Creates a PSP, inheriting the parent’s handles |
| AH | Name | Inputs | Outputs |
|---|---|---|---|
| 25h | DOS_MSC_SETVEC | AL = vector #, DS:DX = address | |
| 2Ah | DOS_MSC_GETDATE | CX = year (1980-2099), DH = month, DL = day, AL = day of week (0 = Sunday) | |
| 2Bh | DOS_MSC_SETDATE | CX = year, DH = month, DL = day | AL = 0 if valid, FFh if not |
| 2Ch | DOS_MSC_GETTIME | CH = hours, CL = minutes, DH = seconds, DL = hundredths | |
| 2Dh | DOS_MSC_SETTIME | CH = hours, CL = minutes, DH = seconds, DL = hundredths | AL = 0 if valid, FFh if not |
| 30h | DOS_MSC_GETVER | See DOS_MSC_GETVER | |
| 33h | DOS_MSC_CTRLC | AL = 0 to get, 1 to set (from DL) | DL = CTRL-C checking state |
| 35h | DOS_MSC_GETVEC | AL = vector # | ES:BX = address |
| 3700h | DOS_MSC_GETSWC | DL = switch character | |
| 3701h | DOS_MSC_SETSWC | DL = switch character | |
| 52h | DOS_MSC_GETVARS | ES:BX -> DOSVARS |
AL returns 02h, so that PC DOS 2.x programs pass their version checks. The other registers identify BASIC-DOS:
DOS_MEM_ALLOC takes a block type in AL, which is stored in the block’s MCB (MCB_TYPE). Types include MCBTYPE_NONE (0) and the types COMMAND.COM uses for its own blocks (‘C’ code, ‘F’ function, ‘V’ variable, ‘S’ string, ‘T’ text, and ‘A’ array). Setting bit 7 of AL (MCBTYPE_HIGH) allocates the block from the top of the last free block that’s large enough, rather than the bottom of the first, so that long-lived blocks don’t fragment the memory below them.
Programs aren’t given all available memory when they’re loaded (see Memory Layout), so a program doesn’t need to shrink its memory before allocating more.
DOS_PSP_EXEC1 (4B01h) is the undocumented PC DOS function that debuggers use to load a program without starting it. BASIC-DOS adds DOS_PSP_EXEC2 (4B02h), which starts a program loaded by DOS_PSP_EXEC1; the current PSP must still be the new program’s PSP.
BASIC-DOS also stores additional information in the PSP, in fields that PC DOS leaves unused (see PSP): the session number (PSP_SCB), the program’s initial stack and start address, its heap, its exit code and exit type, and command-line switches parsed by DOS_UTL_PARSESW.
Environment segments (EPB_ENVSEG) aren’t supported yet, so the field is ignored.
Subdirectories, the read-only attribute, getting and setting file attributes (43h) and file dates and times (57h), and absolute disk reads and writes (INT 25h and INT 26h) aren’t supported yet. Critical errors (INT 24h) aren’t reported to programs yet.
Each session has its own current drive, DTA, switch character, CTRL-C state, and exit, CTRL-C, and critical error handlers, all of which are stored in its SCB. For example, DOS_MSC_SETVEC with vector 23h changes only the current session’s CTRL-C handler.
DOS_PSP_RETCODE returns one of these exit types in AH:
| Value | Name | Meaning |
|---|---|---|
| 0 | EXTYPE_NORMAL | Normal termination |
| 1 | EXTYPE_CTRLC | Terminated by CTRL-C |
| 2 | EXTYPE_ERROR | Terminated by a critical error |
| 3 | EXTYPE_KEEP | Terminated and stayed resident |
| 4 | EXTYPE_DVERR | Terminated by a divide error (BASIC-DOS only) |
| 5 | EXTYPE_OVERR | Terminated by an overflow error (BASIC-DOS only) |
| 6 | EXTYPE_ABORT | Session aborted with CTRL-ALT-DEL (BASIC-DOS only) |
| Value | Name | Meaning |
|---|---|---|
| 1 | ERR_INVALID | Invalid function |
| 2 | ERR_NOFILE | File not found |
| 3 | ERR_NOPATH | Path not found |
| 4 | ERR_NOHANDLE | Out of handles |
| 5 | ERR_ACCDENIED | Access denied |
| 6 | ERR_BADHANDLE | Invalid handle |
| 7 | ERR_BADMCB | Invalid MCB |
| 8 | ERR_NOMEMORY | Out of memory |
| 9 | ERR_BADADDR | Invalid memory segment |
| 15 | ERR_BADDRIVE | Invalid drive |
| 17 | ERR_NOTSAME | Not the same device |
| 39 | ERR_DISKFULL | Disk full |
| 100 | ERR_BADSESSION | Invalid session (BASIC-DOS only) |
| 101 | ERR_NOSESSION | Out of sessions (BASIC-DOS only) |
Copyright (c) 2020-2026 Jeff Parsons Released under MIT License