INT 21h AH=35h reads vector AL from the table at 0000:0000 and returns it as a far pointer: the offset in BX, the segment in ES. Its main job is the first step of hooking a vector: the old address is kept, jumped to by the new handler when it chains, and put back with INT 21h AH=25h at the end.
MOV AX, 3521h ; DOS: get vector 21h, DOS's own entryINT 21h ; ES:BX = the address in the vectorMOV CX, ES ; keep the segmentXOR AX, AXMOV ES, AX ; ES = 0000h: the vector tableMOV DI, 21h * 4 ; vector 21h is the doubleword at 0000:0084hMOV DX, OFFSET OTHER1CMP BX, ES:[DI] ; the offset wordJNE SHOW1CMP CX, ES:[DI+2] ; and the segment wordJNE SHOW1MOV DX, OFFSET SAME1SHOW1:PUSH DSPOP ES ; ES back to the programMOV AH, 09hINT 21hSAME1 DB "35h agrees with the table at 0000:0084", 13, 10, "$"OTHER1 DB "35h and the table differ", 13, 10, "$"
The example shows there is nothing hidden behind the service: the vector of interrupt n is the doubleword at 0000:n × 4, offset first, segment second. Reading it directly works as well, though the DOS call needs no segment register set to 0. For writing, the DOS call is the safe way (see 25h). The usual way to keep a vector:
MOV AX, 3509h ; DOS: get vector 09h, the keyboardINT 21hMOV WORD PTR OLD09, BX ; OLD09 DD 0: offset firstMOV WORD PTR OLD09+2, ES ; then the segmentPUSH DSPOP ES ; ES back to the program
Other uses
A vector also tells whether anything is installed behind it. A vector of 0000:0000, or one pointing at a lone IRET (CFh), means nobody serves that interrupt, and an INT through 0000:0000 jumps into the vector table itself and crashes. Old programs checked vector 33h this way before calling the mouse driver (INT 33h AX=0000h). Resident programs find an earlier copy of themselves by looking for a signature at the address their vector points to.
Pitfalls
The call changes ES. A .COM starts with ES equal to DS, and the string instructions MOVSB, STOSB and SCASB work through ES:DI, so set ES back (PUSH DS / POP ES) before using them. In DOSBox-X most BIOS and DOS vectors point at small callback stubs inside the emulator's BIOS area rather than at real handlers; their addresses are as good as any for chaining.