-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKEYB.ASM
164 lines (137 loc) · 4.27 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
161
162
163
164
;-----------------------------------------------------------
; 32-bit Keyboard functionality.
;-----------------------------------------------------------
IDEAL
P386
MODEL FLAT, C
ASSUME cs:_TEXT,ds:FLAT,es:FLAT,fs:FLAT,gs:FLAT
include "keyb.inc"
;; Copy pasted from example keyboard driver (with some minor tweaks)
;-----------------------------------------------------------
; CODE
;-----------------------------------------------------------
CODESEG
ifdef NASM
extern _DATA
endif
; Installs the custom keyboard handler
proc keyboard_install_handler
push ebp
mov ebp, esp
push eax
push ebx
push ecx
push edx
push edi
push ds
push es
; clear state buffer and the two state bytes
cld
mov ecx, (128 / 2) + 1
mov edi, offset keyb_keyboard_state
xor eax, eax
rep stosw
; store current handler
push es
mov eax, 3509h ; get current interrupt handler 09h
int 21h ; in ES:EBX
mov [word originalKeyboardHandlerS], es ; store SELECTOR
mov [originalKeyboardHandlerO], ebx ; store OFFSET
pop es
; set new handler
push ds
mov ax, cs
mov ds, ax
mov edx, offset keyboardHandler ; new OFFSET
mov eax, 2509h ; set custom interrupt handler 09h
int 21h ; uses DS:EDX
pop ds
pop es
pop ds
pop edi
pop edx
pop ecx
pop ebx
pop eax
mov esp, ebp
pop ebp
ret
endp keyboard_install_handler
; Restores the original keyboard handler
proc keyboard_uninstall_handler
push ebp
mov ebp, esp
push eax
push edx
push ds
mov edx, [originalKeyboardHandlerO] ; retrieve OFFSET
mov ds, [word originalKeyboardHandlerS] ; retrieve SELECTOR
mov eax, 2509h ; set original interrupt handler 09h
int 21h ; uses DS:EDX
pop ds
pop edx
pop eax
mov esp, ebp
pop ebp
ret
endp keyboard_uninstall_handler
; Keyboard handler (Interrupt function, DO NOT CALL MANUALLY!)
proc keyboardHandler
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 eax
push ebx
push esi
push ds
; setup DS for access to data variables
ifndef NASM
mov ax, _DATA
endif
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 [byte keyb_raw_scan_code], 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 ebx, ebx
mov bl, al ; bl now contains the actual scan code ([0;127])
lea esi, [keyb_keyboard_state + ebx] ; load address of key relative to __keyboardState in ebx
mov al, [byte esi] ; 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 [byte keyb_keys_active], al ; update __keysActive counter
mov al, ah
mov [byte esi], al ; update tracked state
pop ds
pop esi
pop ebx
pop eax
iretd
endp keyboardHandler
;-----------------------------------------------------------
; DATA
;-----------------------------------------------------------
DATASEG
originalKeyboardHandlerS dw 0 ; SELECTOR of original keyboard handler
originalKeyboardHandlerO dd 0 ; OFFSET of original keyboard handler
keyb_keyboard_state db 128 dup (?) ; state for all 128 keys
keyb_raw_scan_code db 0 ; scan code of last pressed key
keyb_keys_active db 0 ; number of actively pressed keys
END