DOS keeps one current drive, and every file or directory name without a drive letter refers to it. INT 21h AH=0Eh changes it, which is what the shell does when you type Z: at the prompt. The drive in DL counts from 0: A = 0, B = 1, C = 2, the same numbering INT 21h AH=19h returns. The services that ask about a drive, such as INT 21h AH=36h and INT 21h AH=47h, count from 1 instead and use 0 for the current drive.
There is no error return. Given a drive that does not exist, DOS leaves the current drive as it was and returns AL as usual. To know whether the switch worked, ask with 19h afterwards:
MOV AH, 0Eh ; try drive D:MOV DL, 3INT 21hMOV AH, 19h ; where are we now?INT 21hCMP AL, 3JNE NODRIVE ; still on the old drive: there is no D:
AL comes back with the number of drive letters, not the number of drives. MS-DOS returns the LASTDRIVE setting of CONFIG.SYS (5, A to E, unless set), or the number of block devices if that is larger. DOSBox-X returns one past the highest mounted letter, and since its own drive Z: is always there, the answer is 26.
MOV AH, 19h ; DOS: the current drive in AL, 0 = AINT 21hMOV OLD1, AL ; to come back toCALL PDRVMOV AH, 0Eh ; DOS: select drive DLMOV DL, 25 ; 25 = Z:, DOSBox-X's own driveINT 21hMOV COUNT1, AL ; AL = the number of drive lettersMOV DX, OFFSET ARROW1MOV AH, 09hINT 21hMOV AH, 19h ; did it work?INT 21hCALL PDRVMOV AH, 0Eh ; back to the old driveMOV DL, OLD1INT 21hMOV DX, OFFSET ARROW1MOV AH, 09hINT 21hMOV AH, 19hINT 21hCALL PDRVMOV DX, OFFSET COUNTM1MOV AH, 09hINT 21hMOV AL, COUNT1MOV AH, 0CALL PDECMOV DX, OFFSET CRLFMOV AH, 09hINT 21hOLD1 DB 0COUNT1 DB 0ARROW1 DB " -> $"COUNTM1 DB ", drive letters: $"CRLF DB 13, 10, "$"PDRV PROC NEAR ; print drive AL (0 = A) as "C:"ADD AL, "A"MOV DL, ALMOV AH, 02hINT 21hMOV DL, ":"MOV AH, 02hINT 21hRETPDRV ENDPPDEC PROC NEAR ; print AX in decimal (changes AX BX CX DX)MOV BX, 10XOR CX, CX ; digits on the stackPDEC1:XOR DX, DXDIV BX ; AX = AX / 10, DX = the last digitPUSH DXINC CXOR AX, AXJNZ PDEC1PDEC2:POP DX ; the digits come back first to lastADD DL, "0"MOV AH, 02hINT 21hLOOP PDEC2RETPDEC ENDP
Every drive has its own current directory
DOS remembers a current directory for each drive. Switching to Z: and back to C: lands in the same C: directory as before, and INT 21h AH=3Bh with a path such as D:\GAMES changes the directory of D: without making D: current. The current drive is not part of the program either: a program that switches drives and exits leaves the user on the new drive, so put the old one back first, as the example does.
Floppies
On a PC with one floppy drive, A: and B: are the same physical drive. Selecting B: works, and the first access to it makes DOS ask the user to insert the diskette for drive B:, and to swap again when A: is used. A program that walks through the drives to find disks should use INT 21h AH=36h or an IOCTL call to check each one, not just select it.