INT 21h AH=3Eh ends the use of a handle. For a file that was written, DOS first writes the data still sitting in its buffers to the disk, then updates the directory entry: the new length, and the date and time of the last write (or the stamp set with INT 21h AH=57h). Until that happens the directory may still show the old size, and a crash or a reset loses the end of the file.
The handle number becomes free, and the next open or create can hand it out again. If several handles refer to the same open file (copies made with INT 21h AH=45h, or handles a child program inherited), closing one drops only that handle; the file stays open through the others.
MOV AH, 3Ch ; DOS: create TEST.TXTXOR CX, CX ; CX = 0: normal attributesMOV DX, OFFSET FNAMEINT 21hCALL CHECK ; stop if CF = 1MOV BX, AX ; BX = the handleMOV DX, OFFSET M1MOV AH, 09h ; DOS: print the string at DS:DXINT 21hMOV AH, 3Eh ; DOS: close the handle in BXINT 21hCALL REPORTMOV DX, OFFSET M2MOV AH, 09h ; DOS: print the string at DS:DXINT 21hMOV AH, 3Eh ; the same number againINT 21hCALL REPORT ; CF = 1, AX = 06hMOV AX, 3D00h ; open the file againMOV DX, OFFSET FNAMEINT 21hCALL CHECKMOV DX, OFFSET SAME1CMP AX, BX ; the number that was just freed?JE SHOW1MOV DX, OFFSET OTHER1SHOW1:MOV BX, AX ; BX = the new handleMOV AH, 09hINT 21hMOV AH, 3Eh ; close the handleINT 21hMOV AH, 41h ; delete TEST.TXTMOV DX, OFFSET FNAMEINT 21hFNAME DB "TEST.TXT", 0M1 DB "first close: $"M2 DB "second close: $"SAME1 DB "reopened: the same handle number", 13, 10, "$"OTHER1 DB "reopened: a different handle number", 13, 10, "$"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
The second close fails with 06h, invalid handle: the number no longer refers to anything. The same error comes back for a number that was never opened and for anything above 19.
Standard handles
Handles 0 to 4 can be closed like any other. Closing handle 1 cuts the program off from standard output (INT 21h AH=09h then prints nothing), and the next file opened gets number 1, so whatever the program prints goes into that file. That is one way to redirect output from inside a program; INT 21h AH=45h and 46h do it with a way back.
When a program ends with INT 21h AH=4Ch, DOS closes every handle it still has, so files are not left half-written. Relying on that is poor style, and nothing closes them if the program hangs.
In DOSBox-X a file on a host folder is a host file; the host is sure to see its final contents, length and timestamp once the last handle to it is closed.