How to check keys status in x86 assembly?

后端 未结 3 1608
暖寄归人
暖寄归人 2020-12-11 17:40

I took x86 assembly as a hobby this past january so I could make games that would work on old 8086-powered computers like the PCj and Tandy 1000, but the books I found don\'

3条回答
  •  南笙
    南笙 (楼主)
    2020-12-11 18:01

    Here's how you can do it:

    ; compile with NASM: nasm.exe -f bin kbd.asm -o kbd.com
    
    bits 16
    org 0x100
    
        xor     ax, ax
        mov     es, ax
    
        cli                         ; update ISR address w/ ints disabled
        push    word [es:9*4+2]     ; preserve ISR address
        push    word [es:9*4]
        mov     word [es:9*4], irq1isr
        mov     [es:9*4+2],cs
        sti
    
        call    test
    
        cli                         ; update ISR address w/ ints disabled
        pop     word [es:9*4]       ; restore ISR address
        pop     word [es:9*4+2]
        sti
    
        ret
    
    test:
        mov     ah, 9
        mov     dx, msg1
        int     0x21                ; print "Press and hold ESC"
    
    test1:
        mov     al, [kbdbuf + 1]    ; check Escape key state (Esc scan code = 1)
        or      al, al
        jz      test1               ; wait until it's nonzero (pressed/held)
    
        mov     dx, msg2
        int     0x21                ; print "ESC pressed, release ESC"
    
    test2:
        mov     al, [kbdbuf + 1]    ; check Escape key state (Esc scan code = 1)
        or      al, al
        jnz     test2               ; wait until it's zero (released/not pressed)
    
        mov     dx, msg3            ; print "ESC released"
        int     0x21
    
        ret
    
    irq1isr:
        pusha
    
        ; read keyboard scan code
        in      al, 0x60
    
        ; update keyboard state
        xor     bh, bh
        mov     bl, al
        and     bl, 0x7F            ; bx = scan code
        shr     al, 7               ; al = 0 if pressed, 1 if released
        xor     al, 1               ; al = 1 if pressed, 0 if released
        mov     [cs:bx+kbdbuf], al
    
        ; send EOI to XT keyboard
        in      al, 0x61
        mov     ah, al
        or      al, 0x80
        out     0x61, al
        mov     al, ah
        out     0x61, al
    
        ; send EOI to master PIC
        mov     al, 0x20
        out     0x20, al
    
        popa
        iret
    
    kbdbuf:
        times   128 db 0
    
    msg1 db "Press and hold ESC", 13, 10, "$"
    msg2 db "ESC pressed, release ESC", 13, 10, "$"
    msg3 db "ESC released", 13, 10, "$"
    

    Run it in DOS/Win9x/NT/2K/XP/32-bit Vista/7 or DosBox.

    UPDATE: TASM version:

    ; file: kbdt.asm
    ; compile with TASM/TLINK:
    ;   tasm.exe kbdt.asm
    ;   tlink.exe /t kbdt.obj
    
    .286
    
    code segment use16
    assume cs:code, ds:code, ss:code
    org 100h
    
    main:
        xor     ax, ax
        mov     es, ax
    
        cli                         ; update ISR address w/ ints disabled
        push    word ptr es:[9*4+2]     ; preserve ISR address
        push    word ptr es:[9*4]
        mov     word ptr es:[9*4], offset irq1isr
        mov     es:[9*4+2],cs
        sti
    
        call    test0
    
        cli                         ; update ISR address w/ ints disabled
        pop     word ptr es:[9*4]   ; restore ISR address
        pop     word ptr es:[9*4+2]
        sti
    
        ret
    
    test0:
        mov     ah, 9
        mov     dx, offset msg1
        int     21h                 ; print "Press and hold ESC"
    
    test1:
        mov     al, [kbdbuf + 1]    ; check Escape key state (Esc scan code = 1)
        or      al, al
        jz      test1               ; wait until it's nonzero (pressed/held)
    
        mov     dx, offset msg2
        int     21h                 ; print "ESC pressed, release ESC"
    
    test2:
        mov     al, [kbdbuf + 1]    ; check Escape key state (Esc scan code = 1)
        or      al, al
        jnz     test2               ; wait until it's zero (released/not pressed)
    
        mov     dx, offset msg3     ; print "ESC released"
        int     21h
    
        ret
    
    irq1isr:
        pusha
    
        ; read keyboard scan code
        in      al, 60h
    
        ; update keyboard state
        xor     bh, bh
        mov     bl, al
        and     bl, 7Fh             ; bx = scan code
        shr     al, 7               ; al = 0 if pressed, 1 if released
        xor     al, 1               ; al = 1 if pressed, 0 if released
        mov     cs:[bx+kbdbuf], al
    
        ; send EOI to XT keyboard
        in      al, 61h
        mov     ah, al
        or      al, 80h
        out     61h, al
        mov     al, ah
        out     61h, al
    
        ; send EOI to master PIC
        mov     al, 20h
        out     20h, al
    
        popa
        iret
    
    kbdbuf      db 128 dup (0)
    
    msg1 db "Press and hold ESC", 13, 10, "$"
    msg2 db "ESC pressed, release ESC", 13, 10, "$"
    msg3 db "ESC released", 13, 10, "$"
    
    code ends
    
    end main
    

提交回复
热议问题