INT 21h AH=56h changes a file's name. The old name is at DS:DX and the new one at ES:DI, both ASCIIZ. In a .COM program ES = DS from the start; in an .EXE, ES points to the PSP until you load it, a classic reason for this call to fail with a garbage name.
If the new name has a different directory, the file moves there: its directory entry is taken out of one directory and put into the other, and the data is not copied, so a move is instant whatever the size. Both names must be on the same drive; a different drive is error 11h, not the same device. To move a file to another drive, copy it and delete the original.
| AX | Meaning |
|---|---|
| 02h | the old file does not exist |
| 03h | a directory in either name does not exist |
| 05h | access denied: something already has the new name, or the target directory is full |
| 11h | the names are on different drives |
MOV AH, 3Ch ; create OLD.TXTXOR CX, CXMOV DX, OFFSET OLDNINT 21hCALL CHECKMOV BX, AXMOV AH, 3Eh ; and close itINT 21hMOV AH, 56h ; DOS: renameMOV DX, OFFSET OLDN ; DS:DX = the old nameMOV DI, OFFSET NEWN ; ES:DI = the new name (ES = DS here)INT 21hCALL CHECKMOV DX, OFFSET M1MOV AH, 09h ; DOS: print the string at DS:DXINT 21hMOV DX, OFFSET M2MOV AH, 09h ; DOS: print the string at DS:DXINT 21hMOV AX, 3D00h ; is the old name still there?MOV DX, OFFSET OLDNINT 21hCALL REPORT ; error 02MOV AH, 3Ch ; make a new OLD.TXTXOR CX, CXMOV DX, OFFSET OLDNINT 21hCALL CHECKMOV BX, AXMOV AH, 3EhINT 21hMOV DX, OFFSET M3MOV AH, 09h ; DOS: print the string at DS:DXINT 21hMOV AH, 56h ; rename onto a name that is takenMOV DX, OFFSET NEWNMOV DI, OFFSET OLDNINT 21hCALL REPORT ; error 05MOV AH, 41h ; delete both filesMOV DX, OFFSET OLDNINT 21hMOV AH, 41hMOV DX, OFFSET NEWNINT 21hOLDN DB "OLD.TXT", 0NEWN DB "NEW.TXT", 0M1 DB "renamed OLD.TXT to NEW.TXT", 13, 10, "$"M2 DB "open OLD.TXT: $"M3 DB "rename NEW.TXT to OLD.TXT: $"CRLF DB 13, 10, "$"CHECK PROC NEAR ; CF = 1: print the error code in AL and exitJNC CHECK1PUSH AXMOV DX, OFFSET FAILMSGMOV AH, 09hINT 21hPOP AXCALL PHEXBMOV AX, 4C01h ; exit with code 1INT 21hCHECK1:RETCHECK ENDPFAILMSG DB "failed: error $"REPORT PROC NEAR ; CF = 0: "ok"; CF = 1: "error" and ALJC REPORT1MOV DX, OFFSET OKMSGMOV AH, 09hINT 21hRETREPORT1:PUSH AXMOV DX, OFFSET ERRMSGMOV AH, 09hINT 21hPOP AXCALL PHEXB ; the error codeMOV DX, OFFSET CRLFMOV AH, 09hINT 21hRETREPORT ENDPOKMSG DB "ok", 13, 10, "$"ERRMSG DB "error $"PHEXB PROC NEAR ; print AL as two hex digitsPUSH CXPUSH DXMOV DH, AL ; keep the byteMOV CL, 4SHR AL, CL ; the high digit firstMOV CX, 2PHEXB1:AND AL, 0FhADD AL, "0"CMP AL, "9"JBE PHEXB2ADD AL, 7 ; 10..15 -> "A".."F"PHEXB2:MOV DL, ALMOV AH, 02h ; DOS: print DLINT 21hMOV AL, DH ; then the low digitLOOP PHEXB1POP DXPOP CXRETPHEXB ENDP
Pitfalls
An existing file with the new name is never replaced: delete it first with INT 21h AH=41h if that is what you want. Wildcards are not allowed; rename a group of files one by one, found with INT 21h AH=4Eh. Renaming a file that is open is asking for trouble on MS-DOS: close it first.