Datei kbdc.c:
#include
extern void SetNewIrq9Isr(void);
extern void RestoreOldIrq9Isr(void);
#define SCAN_BUF_SIZE 1024
extern volatile unsigned char ScanBuf[SCAN_BUF_SIZE];
extern volatile unsigned ScanReadIdx;
extern volatile unsigned ScanWriteIdx;
const char ScanToChar[] =
"??1234567890-=??"
"QWERTYUIOP[]??AS"
"DFGHJKL;\"`?\\ZXCV"
"BNM,./??? ";
int IsScanCodeAvailable(void)
{
return ((ScanWriteIdx - ScanReadIdx) & (SCAN_BUF_SIZE - 1)) != 0;
}
unsigned char GetScanCode(void)
{
unsigned char code;
while (!IsScanCodeAvailable());
code = ScanBuf[ScanReadIdx];
ScanReadIdx++;
ScanReadIdx &= SCAN_BUF_SIZE - 1;
return code;
}
int main(void)
{
SetNewIrq9Isr();
printf("Drücken Sie Tasten, um Scan-Codes zu sehen.\nDrücken Sie ESC zum Beenden.\n");
for (;;)
{
unsigned code, symbol;
code = GetScanCode();
symbol = code & 0x7F;
symbol = (symbol < sizeof(ScanToChar)) ? ScanToChar[symbol] : '?';
printf("Scan-Code: 0x%02X, Symbol: \"%c\"\n", code, (char)symbol);
if (code == 1)
{
break;
}
}
RestoreOldIrq9Isr();
return 0;
}
Datei kbda.asm:
GLOBAL _SetNewIrq9Isr, _RestoreOldIrq9Isr
GLOBAL _ScanBuf, _ScanReadIdx, _ScanWriteIdx
SEGMENT _TEXT PUBLIC CLASS=CODE USE16
; void SetNewIrq9Isr(void);
_SetNewIrq9Isr:
push bx
push es
mov bx, 9 * 4
mov ax, 0
mov es, ax
cli
mov ax, [es:bx]
mov [_pOldIrq9Isr], ax
mov word [es:bx], _NewIrq9Isr
mov ax, [es:bx + 2]
mov [_pOldIrq9Isr + 2], ax
mov [es:bx + 2], cs
sti
pop es
pop bx
ret
; void RestoreOldIrq9Isr(void);
_RestoreOldIrq9Isr:
push bx
push es
mov bx, 9 * 4
mov ax, 0
mov es, ax
cli
mov ax, [_pOldIrq9Isr]
mov [es:bx], ax
mov ax, [_pOldIrq9Isr + 2]
mov [es:bx + 2], ax
sti
pop es
pop bx
ret
_NewIrq9Isr:
pusha
push ds
mov ax, _DATA
mov ds, ax
in al, 60h
push ax
in al, 061h
mov ah, al
or al, 080h
out 061h, al
mov al, ah
out 061h, al
pop ax
; ScanBuf[ScanWriteIdx] = scan code;
; ScanWriteIdx = (ScanWriteIdx + 1) & (SCAN_BUF_SIZE - 1);
mov bx, [_ScanWriteIdx]
mov [_ScanBuf + bx], al
inc bx
and bx, 1023
mov [_ScanWriteIdx], bx
mov al, 20h
out 20h, al
pop ds
popa
iret
SEGMENT _DATA PUBLIC CLASS=DATA
_pOldIrq9Isr resd 1
; #define SCAN_BUF_SIZE 1024
; volatile unsigned char ScanBuf[SCAN_BUF_SIZE];
; volatile unsigned ScanReadIdx = 0;
; volatile unsigned ScanWriteIdx = 0;
_ScanBuf resb 1024
_ScanReadIdx dw 0
_ScanWriteIdx dw 0
Ausgabe:
Drücken Sie Tasten, um Scan-Codes zu sehen.
Drücken Sie ESC zum Beenden.
Scan-Code: 0x10, Symbol: "Q"
Scan-Code: 0x90, Symbol: "Q"
Scan-Code: 0x11, Symbol: "W"
Scan-Code: 0x91, Symbol: "W"
Scan-Code: 0x12, Symbol: "E"
Scan-Code: 0x92, Symbol: "E"
Scan-Code: 0x02, Symbol: "1"
Scan-Code: 0x82, Symbol: "1"
Scan-Code: 0x03, Symbol: "2"
Scan-Code: 0x83, Symbol: "2"
Scan-Code: 0x04, Symbol: "3"
Scan-Code: 0x84, Symbol: "3"
Scan-Code: 0x01, Symbol: "?"
Jetzt einige Worte zur Kompilierung:
Kompilieren Sie die Assemblerdatei mit NASM using nasm.exe -f obj kbda.asm
. Es wird kbda.obj
erzeugt. Erstellen Sie ein Projekt in der Borland/Turbo C/C++ IDE, fügen Sie kbdc.c
und kbda.obj
hinzu. Stellen Sie sicher, dass der Code im kleinen oder winzigen Speichermodell kompiliert wird (wir müssen im Grunde sicherstellen, dass SetNewIrq9Isr()
und RestoreOldIrq9Isr()
als Near-Funktionen aufgerufen werden). Kompilieren Sie es.
Es gibt ein paar Einschränkungen.
Erstens werden keine der Funktionen getc()
, gets()
, scanf()
, etc. funktionieren, wenn sie zwischen SetNewIrq9Isr()
und RestoreOldIrq9Isr()
aufgerufen werden. Sie werden das Programm zum Absturz bringen.
Zweitens hält der Code den Status der Tasten shift
, control
und alt
nicht fest. Das bedeutet, dass, wenn Sie dieses Programm von der IDE aus ausführen, indem Sie strg+F9
drücken, die IDE wahrscheinlich denkt, dass strg
immer noch gedrückt ist, wenn das Programm endet. Um die Tastatur zu "entsperren", müssen Sie strg
drücken und loslassen. Das Gleiche gilt möglicherweise für andere ähnliche Tasten, wenn sie gedrückt sind, wenn dieses Programm startet. Sie können zusätzlichen Code einfügen, um zu warten, bis alle Tasten shift
, control
und alt
losgelassen sind. Ich glaube, Sie können ihren aktuellen Status im BIOS-Datenbereich finden.
Sie können natürlich die Assemblerdatei von NASM-Syntax in TASM-Syntax konvertieren und sie mit TASM kompilieren. Ich verwende einfach kostenlose Tools, Turbo C++ 1.01 und NASM.
Aktualisierung: Hier ist die asm-Datei für TASM:
PUBLIC _SetNewIrq9Isr, _RestoreOldIrq9Isr
PUBLIC _ScanBuf, _ScanReadIdx, _ScanWriteIdx
.386
_TEXT SEGMENT PUBLIC 'CODE' USE16
ASSUME CS:_TEXT, DS:_DATA
; void SetNewIrq9Isr(void);
_SetNewIrq9Isr PROC NEAR
push bx
push es
mov bx, 9 * 4
mov ax, 0
mov es, ax
cli
mov ax, es:[bx]
mov _pOldIrq9IsrOfs, ax
mov word ptr es:[bx], offset _NewIrq9Isr
mov ax, es:[bx + 2]
mov _pOldIrq9IsrSeg, ax
mov es:[bx + 2], cs
sti
pop es
pop bx
ret
_SetNewIrq9Isr ENDP
; void RestoreOldIrq9Isr(void);
_RestoreOldIrq9Isr PROC NEAR
push bx
push es
mov bx, 9 * 4
mov ax, 0
mov es, ax
cli
mov ax, _pOldIrq9IsrOfs
mov es:[bx], ax
mov ax, _pOldIrq9IsrSeg
mov es:[bx + 2], ax
sti
pop es
pop bx
ret
_RestoreOldIrq9Isr ENDP
_NewIrq9Isr PROC NEAR
pusha
push ds
mov ax, _DATA
mov ds, ax
in al, 60h
push ax
in al, 061h
mov ah, al
or al, 080h
out 061h, al
mov al, ah
out 061h, al
pop ax
; ScanBuf[ScanWriteIdx] = scan code;
; ScanWriteIdx = (ScanWriteIdx + 1) & (SCAN_BUF_SIZE - 1);
mov bx, _ScanWriteIdx
mov _ScanBuf[bx], al
inc bx
and bx, 1023
mov _ScanWriteIdx, bx
mov al, 20h
out 20h, al
pop ds
popa
iret
_NewIrq9Isr ENDP
_TEXT ENDS
_DATA SEGMENT PUBLIC 'DATA' USE16
_pOldIrq9IsrOfs dw ?
_pOldIrq9IsrSeg dw ?
; #define SCAN_BUF_SIZE 1024
; volatile unsigned char ScanBuf[SCAN_BUF_SIZE];
; volatile unsigned ScanReadIdx = 0;
; volatile unsigned ScanWriteIdx = 0;
_ScanBuf db 1024 dup (?)
_ScanReadIdx dw 0
_ScanWriteIdx dw 0
_DATA ENDS
END
Kompilieren Sie es mit tasm.exe /ml kbda.asm
. Der Rest ist gleich.