-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKEYB.ASM
160 lines (128 loc) · 4.3 KB
/
KEYB.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
; ==============================================================================
; Keyboard functionality.
; ==============================================================================
.MODEL large ; multiple data segments and multiple code segments
; --- INCLUDES -----------------------------------------------------------------
INCLUDE keyb.inc
; --- MACROS AND CONSTANTS -----------------------------------------------------
; --- DATA SEGMENT -------------------------------------------------------------
.DATA?
PUBLIC __keyboardState, __rawScanCode, __keysActive
__originalKeyboardHandler dw 2 dup(?) ; SEG/OFF of original keyboard handler
__keyboardState db 128 dup(?) ; state for all 128 keys
__rawScanCode db ? ; scan code of last pressed key
__keysActive db ? ; number of actively pressed keys
; --- CODE SEGMENT -------------------------------------------------------------
.CODE
; Installs the custom keyboard handler
installKeyboardHandler PROC FAR
push bp
mov bp, sp
push ax
push bx
push cx
push dx
push di
push ds
push es
mov ax, seg __originalKeyboardHandler
mov ds, ax
mov es, ax
; clear state buffer and the two state bytes
cld
mov cx, (128 / 2) + 1
mov di, offset __keyboardState
xor ax, ax
rep stosw
; store current handler
mov ax, 3509h ; get current interrupt handler 09h
int 21h ; in ES:BX
mov ax, es
mov [__originalKeyboardHandler][0], ax ; store SEG
mov [__originalKeyboardHandler][2], bx ; store OFF
; set new handler
mov ax, seg keyboardHandler ; new SEG
mov dx, offset keyboardHandler ; new OFF
mov ds, ax
mov ax, 2509h ; set custom interrupt handler 09h
int 21h ; uses DS:DX
pop es
pop ds
pop di
pop dx
pop cx
pop bx
pop ax
pop bp
ret
installKeyboardHandler ENDP
; Restores the original keyboard handler
uninstallKeyboardHandler PROC FAR
push bp
mov bp, sp
push ax
push dx
push ds
mov ax, seg __originalKeyboardHandler
mov ds, ax
mov ax, [__originalKeyboardHandler][0] ; retrieve SEG
mov dx, [__originalKeyboardHandler][2] ; retrieve OFF
mov ds, ax
mov ax, 2509h ; set original interrupt handler 09h
int 21h ; uses DS:DX
pop ds
pop dx
pop ax
pop bp
ret
uninstallKeyboardHandler ENDP
; Keyboard handler (Interrupt function, DO NOT CALL MANUALLY!)
keyboardHandler PROC FAR
KEY_BUFFER EQU 60h ; the port of the keyboard buffer
KEY_CONTROL EQU 61h ; the port of the keyboard controller
PIC_PORT EQU 20h ; the port of the peripheral
push ax
push bx
push si
push ds
; setup DS for access to data variables
mov ax, seg __originalKeyboardHandler
mov ds, ax
; handle the keyboard input
sti ; re-enable CPU interrupts
in al, KEY_BUFFER ; get the key that was pressed from the keyboard
mov bl, al ; store scan code for later use
mov [__rawScanCode], al ; store the key in global variable
in al, KEY_CONTROL ; set the control register to reflect key was read
or al, 82h ; set the proper bits to reset the keyboard flip flop
out KEY_CONTROL, al ; send the new data back to the control register
and al, 7fh ; mask off high bit
out KEY_CONTROL, al ; complete the reset
mov al, 20h ; reset command
out PIC_PORT, al ; tell PIC to re-enable interrupts
; process the retrieved scan code and update __keyboardState and __keysActive
; scan codes of 128 or larger are key release codes
mov al, bl ; put scan code in al
shl ax, 1 ; bit 7 is now bit 0 in ah
not ah
and ah, 1 ; ah now contains 0 if key released, and 1 if key pressed
shr al, 1 ; al now contains the actual scan code ([0;127])
xor bx, bx
mov bl, al ; bl now contains the actual scan code ([0;127])
lea si, [__keyboardState][bx] ; load address of key relative to __keyboardState in bx
mov al, [si] ; load the keyboard state of the scan code in al
; al = tracked state (0 or 1) of pressed key (the value in memory)
; ah = physical state (0 or 1) of pressed key
neg al
add al, ah ; al contains -1, 0 or +1 (-1 on key release, 0 on no change and +1 on key press)
add [__keysActive], al ; update __keysActive counter
mov al, ah
mov [si], al ; update tracked state
pop ds
pop si
pop bx
pop ax
iret
keyboardHandler ENDP
; _------------------------------- END OF CODE ---------------------------------
END