INT 33h AX=0003h is the polling interface to the mouse: it returns the pointer's position and the buttons held down at this moment. It does not wait and does not consume anything, so a program calls it once per frame and acts on the answer.
| Register | Returns |
|---|---|
| CX | x, 0..639 for most modes (0..638 in steps of 2 in mode 13h) |
| DX | y, 0..199 in 80×25 text and the 200-line modes, 0..479 in mode 12h |
| BX bit 0 | left button down |
| BX bit 1 | right button down |
| BX bit 2 | middle button down (three-button mice) |
In text mode divide both coordinates by 8 to get the column and row of the character under the pointer; the driver keeps them at multiples of 8 there anyway. The example places the pointer on column 10, row 5, reads it back once and converts:
XOR AX, AX ; reset the driverINT 33hMOV AX, 0004h ; put the pointer on column 10, row 5MOV CX, 10*8 ; x = column x 8MOV DX, 5*8 ; y = row x 8INT 33hMOV AX, 0003h ; read position and buttons, onceINT 33h ; CX = x, DX = y, BX = buttonsMOV SI, CX ; keep them: printing uses DXMOV DI, DXMOV AX, SICALL PDEC ; x: 80MOV DL, " "MOV AH, 02h ; DOS: print the character in DLINT 21hMOV AX, DICALL PDEC ; y: 40MOV DL, " "MOV AH, 02h ; DOS: print the character in DLINT 21hMOV AX, BXAND AX, 0007h ; the three button bitsCALL PDEC ; 0: nothing pressedMOV DX, OFFSET ARROW1MOV AH, 09h ; DOS: print the $-string at DS:DXINT 21hMOV CL, 3MOV AX, SISHR AX, CL ; column = x / 8CALL PDEC ; 10MOV DL, ","MOV AH, 02h ; DOS: print the character in DLINT 21hMOV AX, DISHR AX, CL ; row = y / 8CALL PDEC ; 5ARROW1 DB " -> $"PDEC PROC NEAR ; print AX in decimal; keeps every registerPUSH AXPUSH BXPUSH CXPUSH DXMOV BX, 10XOR CX, CX ; digits on the stackDECD1:XOR DX, DXDIV BX ; AX = AX / 10, DX = the last digitPUSH DXINC CXTEST AX, AXJNZ DECD1DECD2:POP DX ; the digits come back first to lastADD DL, "0"MOV AH, 02hINT 21hLOOP DECD2POP DXPOP CXPOP BXPOP AXRETPDEC ENDP
Clicks
BX is the state now, not a history. A click shorter than the time between two polls is missed entirely, and a button held down is seen as "pressed" on every poll. To react once per click, remember the previous BX and act when a bit goes from 0 to 1. To catch clicks that happen between polls, use AX=0005h (presses since the last call, with the position of the last one) or an event handler, INT 33h AX=000Ch.
MOV AX, 0003hINT 33hMOV AX, BXXOR AX, OLDB1 ; bits that changed since the last pollAND AX, BX ; ...and are down now: fresh pressesMOV OLDB1, BXTEST AL, 1 ; the left button went downJNZ CLICK1
Upper bits of BX are not always zero: drivers with wheel support (CuteMouse, DOSBox-X) put the wheel movement in BH. Mask with AND BX, 7 before comparing.