Appendix of System Calls for DOS
The following Interrupts are hand picked by Chastity for their usefulness in reading and writing characters in text based DOS programs. Most, but not all of these have already been used in this book. This does not cover BIOS calls for moving the console cursor, changing color of text, or changing video modes.
These were originally copied from the files “INTERRUP.F” in Ralf Brown’s Interrupt List. However, the formatting was not compatible with Markdown and so I have made some effort to make it readable on modern devices that certainly didn’t exist when Ralf Brown was alive and DOS was in common usage. This information is essential for knowing which numbers to put in which registers.
D-2100-TERMINATE PROGRAM
INT 21 - DOS 1+ - TERMINATE PROGRAM AH = 00h CS = PSP segment
Although this call will often end the program, it does not return a value back to the operating system like INT 21/AH=4Ch does. However, it can save a few bytes when trying to make the smallest .com files, so it is worth mentioning.
D-2101-READ CHARACTER
INT 21 - DOS 1+ - READ CHARACTER FROM STANDARD INPUT, WITH ECHO
1 AH = 01h
Return: AL = character read
This could be used to read characters one at a time for reading a string.
D-2102-WRITE CHARACTER
INT 21 - DOS 1+ - WRITE CHARACTER TO STANDARD OUTPUT
1 AH = 02h
2 DL = character to write
Return: AL = last character output
As used at the beginning of this book, it prints a single character represented by the number in DL. It can be seen as the equivalent of C’s “putchar”.
D-2109-WRITE STRING
INT 21 - DOS 1+ - WRITE STRING TO STANDARD OUTPUT
1 AH = 09h
2 DS:DX -> '$'-terminated string
Return: AL = 24h (the ‘$’ terminating the string
This function is weird. It prints a string until it finds a dollar sign. This was a way that strings were terminated before the convention of zero terminators like in C or C++ became common. You can save a few bytes by terminating your strings with $ instead of zero. My putstring method expects zero because I follow the modern convention.
D-2139-MKDIR
INT 21 - DOS 2+ - “MKDIR” - CREATE SUBDIRECTORY
1 AH = 39h
2 DS:DX -> ASCIZ pathname
Return: CF clear if successful AX destroyed CF set on error AX = error code (03h,05h) (see #01680 at AH=59h/BX=0000h)
I am not sure why someone would create a directory inside an assembly program since it could be done before the program is run and also included in a zip file if someone distributes their programs to other people, but this system call is most likely how DOS’s mkdir command is implemented because it is an important thing to do!
D-213A-RMDIR
INT 21 - DOS 2+ - “RMDIR” - REMOVE SUBDIRECTORY
1 AH = 3Ah
2 DS:DX -> ASCIZ pathname of directory to be removed
Return: CF clear if successful AX destroyed CF set on error AX = error code (03h,05h,06h,10h) (see #01680 at AH=59h/BX=0000h)
Notes: directory must be empty (contain only ‘.’ and ‘..’ entries)
D-213B-CHDIR
INT 21 - DOS 2+ - “CHDIR” - SET CURRENT DIRECTORY
1 AH = 3Bh
2 DS:DX -> ASCIZ pathname to become current directory
3 (max 64 bytes)
Return: CF clear if successful AX destroyed CF set on error AX = error code (03h) (see #01680 at AH=59h/BX=0000h)
Notes: if new directory name includes a drive letter, the default drive is not changed, only the current directory on that drive
D-213C-CREAT
INT 21 - DOS 2+ - “CREAT” - CREATE OR TRUNCATE FILE
1 AH = 3Ch
2 CX = file attributes (see #01401)
3 DS:DX -> ASCIZ filename
Return: CF clear if successful AX = file handle CF set on error AX = error code (03h,04h,05h) (see #01680 at AH=59h/BX=0000h)
Notes: if a file with the given name exists, it is truncated to zero length
Bitfields for file attributes: Bit(s) Description (Table 01401) 0 read-only 1 hidden 2 system 3 volume label (ignored) 4 reserved, must be zero (directory) 5 archive bit 7 if set, file is shareable under Novell NetWare
D-213D-OPEN
INT 21 - DOS 2+ - “OPEN” - OPEN EXISTING FILE
1 AH = 3Dh
2 AL = access and sharing modes (see #01402)
3 DS:DX -> ASCIZ filename
4 CL = attribute mask of files to look for (server call only)
Return: CF clear if successful AX = file handle CF set on error AX = error code (01h,02h,03h,04h,05h,0Ch,56h) (see #01680 at AH=59h)
Bitfields for access and sharing modes:
Table 01402
Bit(s) Description 2-0 access mode
- 000 read only
- 001 write only
- 010 read/write
D-213E-CLOSE
INT 21 - DOS 2+ - “CLOSE” - CLOSE FILE
1 AH = 3Eh
2 BX = file handle
Return: CF clear if successful AX destroyed CF set on error AX = error code (06h) (see #01680 at AH=59h/BX=0000h)
Notes: if the file was written to, any pending disk writes are performed, the time and date stamps are set to the current time, and the directory entry is updated
D-213F-READ
INT 21 - DOS 2+ - “READ” - READ FROM FILE OR DEVICE
1 AH = 3Fh
2 BX = file handle
3 CX = number of bytes to read
4 DS:DX -> buffer for data
Return: CF clear if successful AX = number of bytes actually read (0 if at EOF before call) CF set on error AX = error code (05h,06h) (see #01680 at AH=59h/BX=0000h)
Notes: data is read beginning at current file position, and the file position is updated after a successful read the returned AX may be smaller than the request in CX if a partial read occurred
D-2140-WRITE
INT 21 - DOS 2+ - “WRITE” - WRITE TO FILE OR DEVICE
1 AH = 40h
2 BX = file handle
3 CX = number of bytes to write
4 DS:DX -> data to write
Return: CF clear if successful AX = number of bytes actually written CF set on error AX = error code (05h,06h) (see #01680 at AH=59h/BX=0000h)
Notes: if CX is zero, no data is written, and the file is truncated or extended to the current position data is written beginning at the current file position, and the file position is updated after a successful write
D-2141-UNLINK
INT 21 - DOS 2+ - “UNLINK” - DELETE FILE
1 AH = 41h
2 DS:DX -> ASCIZ filename (no wildcards, but see notes)
3 CL = attribute mask for deletion (server call only, see notes)
Return: CF clear if successful AX destroyed (DOS 3.3) AL seems to be drive of deleted file CF set on error AX = error code (02h,03h,05h) (see #01680 at AH=59h/BX=0000h)
Notes: (DOS 3.1+) wildcards are allowed if invoked via AX=5D00h, in which case the filespec must be canonical (as returned by AH=60h), and only files matching the attribute mask in CL are deleted DR DOS 5.0-6.0 returns error code 03h if invoked via AX=5D00h; DR DOS 3.41 crashes if called via AX=5D00h with wildcards DOS does not erase the file’s data; it merely becomes inaccessible
D-2142-LSEEK
INT 21 - DOS 2+ - “LSEEK” - SET CURRENT FILE POSITION
1 AH = 42h
2 AL = origin of move
3 00h start of file
4 01h current file position
5 02h end of file
6 BX = file handle
7 CX:DX = (signed) offset from origin of new file position
Return: CF clear if successful DX:AX = new file position in bytes from start of file CF set on error AX = error code (01h,06h) (see #01680 at AH=59h/BX=0000h)
Notes: for origins 01h and 02h, the pointer may be positioned before the start of the file; no error is returned in that case (except under Windows NT), but subsequent attempts at I/O will produce errors if the new position is beyond the current end of file, the file will be extended by the next write (see AH=40h);
D-214300-GET FILE ATTRIBUTES
INT 21 - DOS 2+ - GET FILE ATTRIBUTES
1 AX = 4300h
2 DS:DX -> ASCIZ filename
Return: CF clear if successful CX = file attributes (see #01420) AX = CX (DR DOS 5.0) CF set on error AX = error code (01h,02h,03h,05h) (see #01680 at AH=59h) Notes: under the FlashTek X-32 DOS extender, the filename pointer is in DS:EDX under DR DOS 3.41 and 5.0, attempts to change the subdirectory bit are simply ignored without an error BUG: Windows for Workgroups returns error code 05h (access denied) instead of error code 02h (file not found) when attempting to get the attributes of a nonexistent file. This causes open() with O_CREAT and fopen() with the “w” mode to fail in Borland C++. SeeAlso: AX=4301h,AX=4310h,AX=7143h,AH=B6h,INT 2F/AX=110Fh,INT 60/DI=0517h
D-214301-CHMOD
INT 21 - DOS 2+ - “CHMOD” - SET FILE ATTRIBUTES
1 AX = 4301h
2 CX = new file attributes (see #01420)
3 DS:DX -> ASCIZ filename
Return: CF clear if successful AX destroyed CF set on error AX = error code (01h,02h,03h,05h) (see #01680 at AH=59h)
Notes: will not change volume label or directory attribute bits, but will change the other attribute bits of a directory (the directory bit must be cleared to successfully change the other attributes of a directory, but the directory will not be changed to a normal file as a result) MS-DOS 4.01 reportedly closes the file if it is currently open for security reasons, the Novell NetWare execute-only bit can never be cleared; the file must be deleted and recreated under the FlashTek X-32 DOS extender, the filename pointer is in DS:EDX DOS 5.0 SHARE will close the file if it is currently open in sharing-compatibility mode, otherwise a sharing violation critical error is generated if the file is currently open DR DOS 3.41/5.0 will silently ignore attempts to change the ‘directory’ attribute bit SeeAlso: AX=4300h,AX=4311h,AX=7143h,INT 2F/AX=110Eh
Bitfields for file attributes: Bit(s) Description (Table 01420) 7 shareable (Novell NetWare) 7 pending deleted files (Novell DOS, OpenDOS) 6 unused 5 archive 4 directory 3 volume label execute-only (Novell NetWare) 2 system 1 hidden 0 read-only
D-214C-EXIT
INT 21 - DOS 2+ - “EXIT” - TERMINATE WITH RETURN CODE
1 AH = 4Ch
2 AL = return code
Return: never returns
Notes: unless the process is its own parent (see #01378 [offset 16h] at AH=26h), all open files are closed and all memory belonging to the process is freed all network file locks should be removed before calling this function
SeeAlso: AH=00h,AH=26h,AH=4Bh,AH=4Dh,INT 15/AH=12h/BH=02h,INT 20,INT 22 SeeAlso: INT 60/DI=0601h
D-2159-GET ERROR INFO
INT 21 - DOS 3.0+ - GET EXTENDED ERROR INFORMATION
1 AH = 59h
2 BX = 0000h
Return: AX = extended error code (see #01680) BH = error class (see #01682) BL = recommended action (see #01683) CH = error locus (see #01684) ES:DI may be pointer (see #01681, #01680) CL, DX, SI, BP, and DS destroyed
Notes: functions available under DOS 2.x map the true DOS 3.0+ error code into one supported under DOS 2.x you should call this function to retrieve the true error code when an FCB or DOS 2.x call returns an error under DR DOS 5.0, this function does not use any of the DOS-internal stacks and may thus be called at any time
SeeAlso: AH=59h/BX=0001h,AX=5D0Ah,INT 2F/AX=122Dh,INT 24
Table 01680
Values for DOS extended error code:
- 00h (0) no error
- 01h (1) function number invalid
- 02h (2) file not found
- 03h (3) path not found
- 04h (4) too many open files (no handles available)
- 05h (5) access denied
- 06h (6) invalid handle
- 07h (7) memory control block destroyed
- 08h (8) insufficient memory
- 09h (9) memory block address invalid
- 0Ah (10) environment invalid (usually >32K in length)
- 0Bh (11) format invalid
- 0Ch (12) access code invalid
- 0Dh (13) data invalid
- 0Eh (14) reserved
- 0Eh (14) (PTS-DOS 6.51+, S/DOS 1.0+) fixup overflow
- 0Fh (15) invalid drive
- 10h (16) attempted to remove current directory
- 11h (17) not same device
- 12h (18) no more files
- 13h (19) disk write-protected
- 14h (20) unknown unit
- 15h (21) drive not ready
- 16h (22) unknown command
- 17h (23) data error (CRC)
- 18h (24) bad request structure length
- 19h (25) seek error
- 1Ah (26) unknown media type (non-DOS disk)
- 1Bh (27) sector not found
- 1Ch (28) printer out of paper
- 1Dh (29) write fault
- 1Eh (30) read fault
- 1Fh (31) general failure
- 20h (32) sharing violation
- 21h (33) lock violation
- 22h (34) disk change invalid (ES:DI -> media ID structure)(see #01681)
- 23h (35) FCB unavailable
- 23h (35) (PTS-DOS 6.51+, S/DOS 1.0+) bad FAT
- 24h (36) sharing buffer overflow
- 25h (37) (DOS 4.0+) code page mismatch
- 26h (38) (DOS 4.0+) cannot complete file operation (EOF / out of input)
- 27h (39) (DOS 4.0+) insufficient disk space
- 28h-31h reserved
D-2162-GET PSP ADDRESS
INT 21 - DOS 3.0+ - GET CURRENT PSP ADDRESS
1 AH = 62h
Return: BX = segment of PSP for current process
Notes: this function does not use any of the DOS-internal stacks and may thus be called at any time, even during another INT 21h call the current PSP is not necessarily the caller’s PSP identical to the undocumented AH=51h SeeAlso: AH=50h,AH=51h