Calling an interrupt service is more like invoking a system call than it is like writing to a memory-mapped register.
That is, when you invoke a software interrupt, there is no guarantee that the register values will be the same that they have been before the interrupt call. In fact, most of the time, they will not be, unless the interrupt service routine is a no-op placeholder. Modifying register state is how the interrupt handler will communicate its presence, adherence to the expected calling protocol and any potential result to the caller. (Hardware interrupt handlers are another story: since they can be invoked at unpredictable times, they must restore all registers to their original values before returning.) The comparison to syscalls is not a mere metaphor, as software interrupts have in fact been used as a syscall mechanism on a number of x86 operating systems: interrupt 0x80 in Linux, interrupt 0x21 in MS-DOS, and the VxDcall
/VxDjmp
pseudo-instruction in VMM32 (Windows 3.x Enhanced Mode and 9x), which is a specially-formatted interrupt 0x20 instruction.
Ralf Brown’s entry on interrupt 0x33 service 0 has this to say on the AX register:
Return: AX = status
- 0000h hardware/driver not installed
- FFFFh hardware/driver installed
which means that the AX register will be only left unmodified if the mouse driver is absent, demonstrating the principle above. If you increment the FFFFh value returned in AX by service 0, you get zero (thanks to 16-bit wrap-around), which means you end up invoking service 0 again. This is easily seen in a DEBUG session:
C:\>debug
-a
1E8A:0100 mov ax,0
1E8A:0103 int 33
1E8A:0105 inc ax
1E8A:0106 int 33
1E8A:0108
-rax
AX 0000
:abcd
-r
AX=ABCD BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=1E8A ES=1E8A SS=1E8A CS=1E8A IP=0100 NV UP EI PL NZ NA PO NC
1E8A:0100 B80000 MOV AX,0000
-p
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=1E8A ES=1E8A SS=1E8A CS=1E8A IP=0103 NV UP EI PL NZ NA PO NC
1E8A:0103 CD33 INT 33
-p
AX=FFFF BX=0005 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=1E8A ES=1E8A SS=1E8A CS=1E8A IP=0105 NV UP EI PL NZ NA PO NC
1E8A:0105 40 INC AX
-p
AX=0000 BX=0005 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=1E8A ES=1E8A SS=1E8A CS=1E8A IP=0106 NV UP EI PL ZR AC PE NC
1E8A:0106 CD33 INT 33
-
The same RBIL entry notes that the interrupt 0x33 call also modifies BX. You should probably make Show_Mouse
preserve the value of the BX register, or document that the call may modify it. Since you use the stack to preserve AX, I presume you intend to do the former.