获得键盘扫描码


概述:

    在编制键盘输入程序时常常要用到一个键的扫描码或ASC码,如用到 Foxpro 的 inkey() 函数,以及用到 BIOS 的 INT 16H时,但找一个编码表不太容易,有时候找到的编码表又不全,无法查到组合键的编码,本程序就是一个随时用来显示按键的ASC码及扫描码的程序,可以用 16 进制和 10 进制同时显示一个键按下和放开的扫描码,以及ASC码,同样也支持组合键。这里是编译好的可执行文件:scancode.com
    在本程序中,查表的编程方法可用做参考,一般来说,如果程序有以下的结构:

       ...
       cmp     al,value1
       jz      offset1
       cmp      al,value2
       jz      offset2
       cmp     al,value3
       jz      offset3
       ...

且要比较的值很多时,可以考虑查表的方法。程序改为以下结构后,修改起来很容易,可读性也大大增强了,如果要继续添加分支时,只需在表中加上一项就行。

       ...
table  db     value1,value2,value3 ...
table1 dw     offset1,offset2,offset3 ...

        mov    di,offset table
        mov    cx,table的长度
        repnz  scasb
        jnz    not_found

        dec    di
        sub    di,offset table         ;取出表的地址
        mov    si,di
        shl    si,1                    ;x2
        add    si,offset table1
        jmp    [si]                    ;跳转到表中的地址
        ...

   
源程序:

;    Scan code viewer
;    Aug 3,1995
;    by Luo Yun Bin

.286
CODE      SEGMENT
          ASSUME     CS:CODE,DS:CODE
          ORG    100H
start:
          jmp    install

KEY_BUFF  DB    ?             ;INT 9H中按下一个键产生的扫描码
KEY_BUFF1 DB    ?             ;INT 9H中松开一个键产生的扫描码
AAH       DB    ?
AAL       DB    ?

D_COPYRIGHT    DB    "<< ScanCode viewer >>",0dh,0ah
        DB    '(C) Copyright by Luo Yun Bin, May 26,1996',0dh,0ah
        DB    'Phone: 0576-4114689.',0dh,0ah,0ah
        DB    "Press any key to view it's scan code...",0dh,0ah
        DB    'or press Esc key to return DOS...',0dh,0ah,0ah,24h
D_MES1  DB    'Scan Code: %02shh (%2sd) ... '
        DB    'Release: %02shh (%3sd) ... Key: ',0
        DW     KEY_BUFF,KEY_BUFF,KEY_BUFF1,KEY_BUFF1
D_MES2  DB    0dh,0ah,0
D_MES3  DB    'Key value: %02sh%02shh ...... '
        DB     '(AH=%sd,AL=%sd)',0dh,0ah,0ah,0
        DW    AAH,AAL,AAH,AAL
D_MES4  DB    'This is Scan Code viewer by LYB.',0dh,0ah,24h

;键盘扫描码编码表
;                    0123456789abcdef ;
KEY_TABLE    DB    '??1234567890-=??' ;0
             DB     'QWERTYUIOP[]??AS' ;1
             DB     "DFGHJKL;'`?\ZXCV" ;2
             DB     'BNM,./?*????????' ;3
             DB     '??????????-?5?+?' ;4
             DB     '????????????????' ;5
             DB     '????????????????' ;6
             DB     '????????????????' ;7

;特殊键的说明字符串编码表
KEY_TABLE1   DB     3bh,3ch,3dh,3eh,3fh,40h,41h,42h,43h,44h,57h,58h
             DB     0eh,0fh,3ah,2ah,1dh,38h,36h,1ch,39h,1
             DB     52h,53h,47h,4fh,49h,51h,48h,50h,4bh,4dh,46h,45h

;对应上表
KEY_TABLE1_END    EQU    THIS BYTE
          DW     f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12
          DW     bks,tab,cap,lsh,ctr,alt,rsh,ent,spa,_esc
          DW     _ins,del,hom,_end,pgu,pgd,up,dow,lef,rig,sco,num

;特殊键的说明字符串
f1        db    'F1',0         ;
f2        db    'F2',0
f3        db    'F3',0
f4        db    'F4',0
f5        db    'F5',0
f6        db    'F6',0
f7        db    'F7',0
f8        db    'F8',0
f9        db    'F9',0
f10       db    'F10',0
f11       db    'F11',0
f12       db    'F12',0
bks       db    'Back Space',0
tab       db    'Table',0
cap       db    'Caps Lock',0
lsh       db    'Left Shift',0
ctr       db    'Ctrl',0
alt       db    'Alt',0
rsh       db    'Right Shift',0
ent       db    'Enter',0
spa       db    'Space',0
_ins      db    'Insert',0
del       db    'Delete',0
hom       db    'Home',0
_end      db    'End',0
pgu       db    'Page Up',0
pgd       db    'Page Down',0
up        db    'Up',0
dow       db    'Down',0
lef       db    'Left',0
rig       db    'Right',0
sco       db    'Scroll Lock',0
num       db    'Num Lock',0
_esc      db    'Esc',0

PRINT_KEY    PROC

        mov    bl,key_buff             ;取扫描码到BL
        xor    bh,bh
        mov    al,key_table [bx]       ;查扫描码表

        cmp    al,'?'                  ;如果为?则继续查特殊码表
        jz     pk1
pk0:
        call   prt_to_scr
        ret
pk1:
        mov    al,key_buff             ;在特殊码表内扫描
        mov    di,offset key_table1
        mov    cx,offset key_table1_end-offset key_table1
        repnz  scasb
        jnz    pk0

        dec    di
        sub    di,offset key_table1    ;取出说明字符串地址
        mov    si,di
        shl    si,1
        add    si,offset key_table1_end
        mov    si,[si]
        call   printf                  ;显示到屏幕

        ret

PRINT_KEY    ENDP

;新的 INT 09H 键盘中断程序
int9:
        pushf
        pusha
        push    ds
        push    es

        push    cs
        pop     ds
        push    cs
        pop     es

        in      al,60h                 ;读入扫描码
        mov     key_buff,al

        test    al,80h                 ;如果>80H则为放开一个键
        jnz     int9_quit

        or      al,80h
        mov     key_buff1,al

        mov     si,offset d_mes1
        call    printf
        call    print_key
        mov     si,offset d_mes2
        call    printf
int9_quit:
        pop     es
        pop     ds
        popa
        popf

        DB      0EAH
OFF9    DW      ?
SEG9    DW      ?

install:
        mov    ah,9              ;显示版权信息
        mov    dx,offset d_copyright
        int    21h

        mov    ax,3509h          ;保留INT 09H的中断向量
        int    21h
        mov    off9,bx
        mov    seg9,es
        mov    ax,2509h          ;把INT 09H指到 offset int9
        mov    dx,offset int9
        int    21h
        push   cs
        pop    es
lop:
        mov    ah,10h             ;扩展键盘输入
        int    16h

        mov    aah,ah             ;显示键盘输入的编码
        mov    aal,al
        mov    si,offset d_mes3
        call   printf

        cmp    key_buff,1         ;如果非按下Esc,继续循环
        jnz    lop

        lds    dx,dword ptr off9 ;恢复INT 09H中断向量
        mov    ax,2509h
        int    21h

        push   cs
        pop    ds

        mov    ah,9
        mov    dx,offset d_mes4
        int    21h

        int    20h

INCLUDE PRINTF.ASM                ;一个公用的显示子程序

CODE    ENDS
        END    START





(C) Copyright by LuoYunBin's Win32 ASM Page,http://asm.yeah.net