Assembly programozás - 4. rész: A billentyűzet

  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

Előzetes

Soron következő cikkem a szöveges képernyő közvetlen, videomemórián keresztül történő kezelésével foglalkozik.

 

Németh Róbert - nrobcsi@freemail.hu