Obsługa myszy PS/2, składnia NASM-a.
W tej wersji kod nie jest idiotoodporny. Jeśli myszy nie ma (lub jest na COM lub USB) to program się zawiesi w nieskończoność czekając na odpowiedź od myszy.
Testowane w 32-bitowym trybie chronionym, myślę że bez modyfikacji będzie działało w trybach 16-bitowym i rzeczywistym.
mysz_ktory db 1
mysz_bajt1 db ?
mysz_bajt2 db ?
mysz_bajt3 db ?
irq_12_proc:
push eax
in al,60h
mov ah,[mysz_ktory]
cmp ah,3
je .trzeci
cmp ah,2
je .drugi
.pierwszy:
mov [mysz_bajt1],al
inc ah
mov [mysz_ktory],ah
jmp .koniec_myszy
.drugi:
mov [mysz_bajt2],al
inc ah
mov [mysz_ktory],ah
jmp .koniec_myszy
.trzeci:
mov [mysz_bajt3],al
call zdarzenie_myszy
mov ah,1
mov [mysz_ktory],ah
jmp .koniec_myszy
.koniec_myszy:
mov al,20h
out 0A0h,al
mov al,20h
out 20h,al
pop eax
iret
wait_w:
push ax
.full: in al,64h
and al,2
jnz .full
pop ax
ret
wait_r:
push ax
.empty: in al,64h
and al,1
jz .empty
pop ax
ret
; zapis do myszy bajtu z AL
write_mouse:
push ax
call wait_w
mov al,0D4h
out 64h,al
call wait_w
pop ax
out 60h,al
call read_mouse ; odbierz potwierdzenie
ret
; odczyt z myszy bajtu do AL
read_mouse:
call wait_r
in al,60h
ret
key_on:
push ax
call wait_w
mov al, 0AEh
out 64h,al
pop ax
ret
key_off:
push ax
call wait_w
mov al,0ADh
out 64h,al
pop ax
ret
mouse_int_on:
call wait_w
mov al,60h
out 64h,al
call wait_w
mov al,01000011b
out 60h,al
ret
mouse_int_off:
call wait_w
mov al,60h
out 64h,al
call wait_w
mov al,01000001b
out 60h,al
ret
init_mouse:
call key_off ; wyłączenie klawiatury
mov al,0FFh
call write_mouse ; <-- reset myszy
call read_mouse ; --> kod wyjściowy BAT
call read_mouse ; --> device ID
mov al,0F4h
call write_mouse ; <-- zgoda na wysyłanie danych przez mysz
call key_on ; włączenie klawiatury
call mouse_int_on ; zezwolenie na przerwanie od myszy
ret
done_mouse:
call key_off
call wait_w
mov al,0D4h
out 64h,al
call wait_w
mov al,0F5h
out 60h,al ; <-- zabronienie wysyłania danych przez mysz
call mouse_int_off ; zabronienie przerwania od myszy
call key_on
ret
Aby to działało, należy ustawić procedurę irq_12_proc jako obsługę przerwania IRQ 12, i wykonać
call init_mouse
a po zakończeniu programu
call done_mouse
i przywrócić stare przerwanie. Jeśli myszy nie wyłączymy, może być problem z ponowną jej inicjacją, albo dojdzie do zablokowania klawiatury.
Powyższy kod tylko odbiera dane nadchodzące od myszy i wywołuje procedurę zdarzenie_myszy. Procedura ta powinna analizować te dane (zmienne mysz_bajt, mysz_bajt2, mysz_bajt3) zgodnie z protokołem myszy PS/2.
Oto przykładowa procedurka zdarzenie_myszy ? mysz_ppm, spm, lpm są ustawiane na 0 albo 1.
mysz_kx i mysz_ky to współrzędne kursora przeliczone do trybu tekstowego 80x25.
Zaznaczone jest miejsce, gdzie powinien być dodany kod do rysowania i kasowania kursora.
; zmienne do wykorzystania na zewnątrz:
mysz_ppm db 0
mysz_spm db 0
mysz_lpm db 0
mysz_kx db 0
mysz_ky db 0
; zmienne wewnętrzne
mysz_x dw 0
mysz_y dw 49*16
mysz_starekx db 0
mysz_stareky db 0
zdarzenie_myszy:
pushad
; obliczenie nowej pozycji kursora myszki
push bx
xor bx,bx
mov bl,[mysz_bajt2]
mov al,[mysz_bajt1]
and al,16
cmp al,16
jne .xplus
mov bh,0FFh
.xplus:
mov ax,[mysz_x]
add ax,bx
mov [mysz_x],ax
xor bx,bx
mov bl,[mysz_bajt3]
mov al,[mysz_bajt1]
and al,32
cmp al,32
jne .yplus
mov bh,0FFh
.yplus:
mov ax,[mysz_y]
add ax,bx
mov [mysz_y],ax
mov al,[mysz_ky]
mov [mysz_stareky],al
mov al,[mysz_kx]
mov [mysz_starekx],al
mov ax,[mysz_x]
shr ax,4
cmp al,0
jl .xmin
cmp al,79
jg .xmax
jmp .xok
.xmin:
xor al,al
xor bx,bx
mov [mysz_x],bx
jmp .xok
.xmax:
mov al,79
mov bx,79*16
mov [mysz_x],bx
.xok:
mov [mysz_kx],al
mov ax,[mysz_y]
shr ax,4
cmp al,0
jl .ymin
cmp al,49
jg .ymax
jmp .yok
.ymin:
xor al,al
xor bx,bx
mov [mysz_y],bx
jmp .yok
.ymax:
mov al,49
mov bx,49*16
mov [mysz_y],bx
.yok:
neg al
add al,49
mov [mysz_ky],al
pop bx
; czy zmiana pozycji kursora?
mov al,[mysz_starekx]
mov ah,[mysz_kx]
cmp al,ah
jne .ruch
mov al,[mysz_stareky]
mov ah,[mysz_ky]
cmp al,ah
jne .ruch
jmp .bezruchu
.ruch:
; #### - skasuj kursor z pozycji [mysz_starekx]:[mysz_stareky]
; #### - narysuj kursor na pozycji [mysz_kx]:[mysz_ky]
.bezruchu:
; sprawdzenie przycisku lewego
mov al,[mysz_bajt1]
and al,1
mov [mysz_lpm],al
; sprawdzenie przycisku prawego
mov al,[mysz_bajt1]
and al,2
shr al,1
mov [mysz_ppm],al
; sprawdzenie przycisku środkowego
mov al,[mysz_bajt1]
and al,4
shr al,2
mov [mysz_spm],al
popad
ret