A BIOS megszakításoknál már említém, hogy a billentyűzet kezelője a 0x16-os interrupt-ra van gyógyítva. Mit is lehet ezzel a megszakítással kezdeni alapfokon? Tudjuk, hogy a getch (vagyis 0x0-ás függvény) AL-ben adja vissza a billentyű kódját, AH-ban pedig a Scan kódot. Most két táblázatba foglalom a legfontosabb billentyűk kódjait.
Karakterkódok
Enter |
#13 (0x0D) |
Escape |
#27 (0x1B) |
Backspace |
#08 (0x08) |
Tab |
#09 (0x09) |
Space |
#32 (0x20) |
Scan kódok
F1 |
0x3B |
F2 |
0x3C |
F3 |
0x3D |
F4 |
0x3E |
F5 |
0x3F |
F6 |
0x40 |
F7 |
0x41 |
F8 |
0x42 |
F9 |
0x43 |
F10 |
0x44 |
Insert |
0x52 |
Delete |
0x53 |
Home |
0x47 |
End |
0x4F |
Page Up |
0x49 |
Page Down |
0x51 |
FEL |
0x48 |
LE |
0x50 |
BALRA |
0x4B |
JOBBRA |
0x4D |
Ennek tudatában már olyan programot is meg tudunk írni, ami megmondja, hogy
melyik funkcióbillentyűt nyomtuk le. Ha az F10-hez érünk, akkor lépjen ki.
.model
tiny
.code
olvas:
xor ax, ax
int 16h
cmp ah, 44h ; F10
jz vege
cmp ah, 3Bh
jae vizsga ; nagyobb, vagy egyenlő
jmp olvas ; ha egyik sem, akkor vissza
vizsga:
cmp ah, 43h
jle kiir ; ha kisebb, vagy egyenlő
jmp olvas ; vissza, mert nem jó
kiir:
push ax
mov al, 'F' ; F
call putch
pop ax
mov al, ah
sub al, 3Bh
add al, '1' ; kiszámolósdi
call putch
mov al, ' ' ; space
call putch
jmp olvas
vege:
mov ah, 4Ch
int 21h
putch:
mov ah, 0Eh
int 10h
ret
end
Példánkban két trükköt tettem közre, ezek a "xor ax, ax" és a
"jz vege".
Ha két azonos számon elvégzünk egy kizáró vagy kapcsolatot, akkor
a kizárás miatt az összes bitje 0-ra áll be, vagyis ha AX-et saját magával
XOR-oljuk, akkor AX tartalma zéró lesz. Ez azért kellett, mert akkor tudunk a
0x16 interrupt segítségével a billentyűzetről olvasni, ha AH értéke 0. Persze
beállíthattuk volna "mov ah, 0"-val is, de így is...
A kettes számú trükk a JZ használata volt a JE helyett. Megbeszéltük
korábban, hogy az összehasonlításnál végzett kivonásnál nulla lesz az eredmény,
ha a két érték egyezett, akkor miért ne használjunk JE helyett JZ-t, vagyis
Jump if Zero-t. Ez ugyanis akkor ugrik, ha Zero Flag értéke nulla. Ez pedig
csak egyenlő számok esetében lehetséges.
Nézzük, milyen módszerrel csináltunk az F1-es billentyű Scan kódjából
'1' karaktert. A kíírásnál először elmentettük AX regisztert a verembe, mert
előbb kiírunk egy F betűt, ahhoz viszont szükség van AH regiszterre, de most
abban egy Scan kód van, amit nem kellene elvesztenünk - ezért letoljuk a
verembe. Kiírunk egy 'F' betűt, majd elővesszük a régi AX értéket. Első dolgunk
AH értékét AL-be mozgatni, ugyanis abban kell legyen a kiírandó karakter kódja.
Ha ebből a kódból kivonunk 0x3B-t, vagyis az F1 kódját, akkor 0-t
kapunk, de pl F4 esetében 3-at. Ehhez tehát hozzá kell adni az '1' karakter
kódját, ekkor 0 esetben az '1' karaktert kapjuk, 3 esetében pedig ha '1' 0-t
jelent, akkor 3 már '4'-et alapon a '4' karaktert kapjuk. Ennyi az algoritmus
lényege. Ezt a karaktert kiírjuk, majd és még egy Space karaktert is, és
visszatérünk a billentyűzetről való olvasáshoz.
Nos, akkor most írjunk egy olyan programot is, amelyik ESC lenyomásáig
olvas a billentyűzetről, Enter esetén sort emel és csak kisbetűket fogad el.
.model
tiny
.code
olvas:
xor ax, ax
int 16h
cmp al, 27 ; ESC
jz vege
cmp al, 13 ; ENTER
jz soremeles
cmp al, 'a' ; AL-ben vannak a karakterkodok
jae vizsga ; nagyobb, vagy egyenlo
jmp olvas ; ha egyik sem, akkor vissza
vizsga:
cmp al, 'z'
jle kiir ; ha kisebb, vagy egyenlo
jmp olvas ; vissza, mert nem jo
soremeles:
call putch ; AL-ben ENTER van: kiirni
; az
ENTER, vagyis CR (Carriage Return)
;
vezerlokod hatasara
; a sor
elejere kerul a kurzor
mov al, 0Ah ; LF (Line Feed)
;
"sordobás" vezérlőkarakter
call putch
jmp olvas
kiir:
call putch
jmp olvas
vege:
mov ah, 4Ch
int 21h
putch:
mov ah, 0Eh
int 10h
ret
end
Soron következő cikkem a szöveges képernyő közvetlen, videomemórián keresztül történő kezelésével foglalkozik.