DOS INT 21h AH=56h: Rename a Directory Entry Without Assuming a Move
Use DOS INT 21h/AH=56h safely: pass far paths in DS:DX and ES:DI, check carry and AX, respect same-device limits, and avoid overwrite assumptions.
INT 21h/AH=56h is the DOS handle-independent rename call: it changes the directory entry named by one path to a new path. The destination may be in another directory, but the source and destination must be on the same device. This is not a byte-copy operation, does not cross volumes, and does not provide the wildcard transformation rules of the REN command. A successful return says the DOS path operation succeeded; it is not a durability guarantee or a claim that data was copied and verified.
The call is small enough to hide its important details. The caller passes two far pointers in different segment registers, must inspect the carry flag immediately, and should preserve the returned DOS error code when a rename fails. FreeDOS currently routes the call through its path resolver and lower filesystem or redirector layers, so the actual error can depend on the installed kernel, filesystem, sharing state, and network provider.
Pass two complete, valid path strings
The historical MS-DOS 2.0 system-call reference specifies the source path at DS:DX and the destination at ES:DI. Both are null-terminated path strings. The destination is a path, not just a filename: when the operation is intended to rename into a different directory, include that destination directory and a final name. That directory must already exist and must resolve to the same device as the source.
In a tiny-model 16-bit program where both strings are in the data segment, the setup can look like this:
source_path db 'C:\WORK\REPORT.TMP', 0
destination_path db 'C:\WORK\REPORT.NEW', 0
; Assume DS already addresses the segment containing both strings.
mov dx, OFFSET source_path ; DS:DX -> old path
mov di, OFFSET destination_path
push ds
pop es ; ES:DI -> new path
mov ax, 5600h ; AH=56h, AL is not used here
int 21h
jc rename_failed ; AX contains the DOS error code
; The rename completed. Continue with the success path.
This is an assembly fragment, not a complete .COM program: initialize the data segment and stack according to the executable format and toolchain. If the strings live in different segments, load each far pointer into the required segment:offset pair (DS:DX and ES:DI) instead of copying DS into ES. Do not treat the pointer words themselves as path bytes or pass a near pointer where the API expects a far address.
AL is not an operation selector for this service; the function is chosen by AH=56h. Setting AX=5600h makes the example’s entry state explicit. After INT 21h, do not test a comparison or call a helper before checking CF: those instructions may overwrite the flag that carries the API result. On success, carry is clear. On failure, carry is set and AX reports the DOS error code.
Interpret errors as evidence, not a retry signal
The MS-DOS reference documents these important outcomes:
| Result | Documented meaning | Operational response |
|---|---|---|
error_file_not_found |
The source path does not name a file. | Re-resolve the exact source spelling and parent directory; do not guess a short-name alias. |
error_not_same_device |
The source and destination are on different drives/devices. | Choose a same-device destination or design a separate copy-and-verify workflow. |
error_access_denied |
The source path is a directory, the destination already exists, or DOS cannot create the destination directory entry. | Check each condition separately; do not delete the destination merely to make a retry succeed. |
Those are documented historical categories, not a promise that every filesystem or redirector will report every failure using exactly the same code. FreeDOS’s current dispatcher sends AH=56h through DosRename(). The kernel resolves the destination and source paths, checks that they do not name device entries, and routes the operation to a network redirector when the drive is network-backed. For a local path, its DosRenameTrue() rejects differing drive letters and can return access denied when the sharing layer reports the source as open before calling the filesystem rename routine. Those implementation details explain why an error should be logged with the exact kernel, path, and storage context rather than translated into a single universal diagnosis.
Preserve the original AX before formatting diagnostics. If a program needs the extended DOS error record, query it immediately with the appropriate extended-error call supported by the target DOS; do not make unrelated DOS calls first and assume they leave the last-error context untouched. Keep error reporting out of a critical path if the application has installed custom interrupt or critical-error handling.
Do not confuse rename with command wildcards or copy/delete
The REN command accepts wildcard patterns and substitutes characters from each matched source name. That is a command-line feature; AH=56h receives two path strings for one operation and does not expand *.TMP. FreeDOS command MOVE is a separate utility-level workflow. It may need to copy and then remove data when a same-device rename is not possible, while the interrupt call itself returns a same-device error instead of doing that work for the caller.
There is also a distinct long-filename extension family. Windows 95-style AX=7156h is not the same entry point as legacy AH=56h; it belongs to the 71xxh extension interface and has its own capability and provider requirements. FreeDOS LFN support may involve an external driver. A caller that needs long-name semantics should probe and use the matching LFN contract instead of assuming that the short-name API automatically accepts every spelling in the mounted namespace.
Plan the destination before changing it
Before calling the function, resolve the source and destination independently. Confirm the source is the intended file, the parent of the destination exists, both paths identify the same device, and the destination name is absent if replacement would be unsafe. These checks improve diagnostics but are not atomic: another program can create or rename an entry between the check and the interrupt call. The return status remains authoritative.
If the destination already exists, AH=56h is not a portable “replace it” request. The documented access-denied case includes an existing destination. A delete-then-rename sequence creates a window where neither the old nor new name is present and can lose the previous file if the second operation fails. If the application needs replacement semantics, make the loss and recovery policy explicit, preserve the old value, and test the exact filesystem and redirector behavior. Do not describe a rename as a transaction unless the relevant storage implementation documents the required atomicity and persistence guarantees.
The same device restriction is also more precise than “the same directory.” A same-volume rename into another directory can be valid when the destination path resolves correctly. Conversely, two paths that look similar or share a textual prefix may resolve through different drive mappings or redirectors. Compare resolved device context, not string prefixes.
Test on the DOS environment that will run the program
Use a disposable disk image or copied directory. Exercise a normal rename, a destination in another directory on the same device, a missing source, an existing destination, a missing destination parent, a directory source, an open source under the target sharing configuration, and paths that resolve through the intended network redirector. Capture CF, AX, the paths, the drive mapping, and the kernel version for each case. Then verify directory entries and file hashes separately: a rename operation should preserve the underlying file contents, but checking the content is a test of your workflow, not an output guarantee provided by the interrupt call.
Keep classic AH=56h tests separate from the LFN AX=7156h tests. Run the latter only when the actual LFN provider is present, and record whether the volume supports the requested namespace. A version string, a successful short-name rename, or a DOSBox-compatible result is not proof that another FreeDOS installation has identical redirector and LFN behavior.
AH=56h is a precise rename interface when the program supplies the right far paths and treats errors honestly. Use it for a same-device directory-entry change; use a different, explicitly tested workflow when the requirement is wildcard transformation, cross-device movement, overwrite, or verified copy.
Related:
- FreeDOS REN: Plan Wildcard Renames Before Changing Directory Entries
- DOS INT 21h File Creation: Temporary Names and No-Clobber Semantics
Sources: