PDA

View Full Version : کار با سخت افزار صفحه کلید(آموزشی)



amin joon
شنبه 10 دی 1384, 12:48 عصر
با سلام

این مقاله شامل موارد زیر است:

مقدمه ای بر سخت افزار کیبرد و نحوه ی کار با پرت های آن
چند وقفه ی داس و bios برای کار با کیبرد
کار وقفه ی 16 و مثالی از نحوه ی نوشتن وقفه ی 16
کار وقفه ی 9 و مثالی از نحوه ی نوشتن این وقفه

نمیدونم چرا دکمه ی اتچ حذف شده!!!! یه فایل word هست که مورد 1 رو توضیح میده (البته این فایل رو بخاطر درس زبان تخصصی ترجمه کردم ولی بد نیست یه نگاهی بهش بندازید)
این فایل رو وقتی که مشکل سایت رفع شد اتچ میکنم

بقیه ی بحث:

amin joon
شنبه 10 دی 1384, 12:56 عصر
3- رابط داس برای کیبرد


--------------------------------------------------------------------------------

Dos تعداد زیادی تابع برای خواندن کاراکتر از صفحه کلید تامین کرده. نکته‏ای که درباره‏ی توابع داس وجود دارد این است که، این توابع تنها یک مقدار را بر می‏کرداند؛ این به این معنی است که مقدار اسکن‏کدی که روتین سرویس‏ وقفه در بافر صفحه کلید قرار می‏دهد از دست می‏رود.


اگر شما کلیدی را فشار دهید که به جای کد اسکی، باعث ایجاد کد توسعه یافته شود، MSDOS دو کد را بر می‏گرداند؛ کد اول حاوی مقدار صفر است. این به شما می‏گوید که شما باید روتین خواندن کاراکتر را مجددا صدا بزنید.کدی که MSDOS در فراخوانی دوم بر می‏گرداند حاوی کد توسعه یافته‏ی کلید است.

نکته‏ی دیگر اینکه توابع کتابخانه‏ی استاندارد، از روتین های DOS برای خواندن کاراکترها استفاده می‏کند؛ به همین دلیل است که زیرروال getc که در کتابخانه‏ی استاندارد است، کدهای توسعه یافته را به این شکل بر می‏گرداند.



4- رابط بایوس صفحه کلید


--------------------------------------------------------------------------------


اگرچه DOS یک سری توابع کار آمد را برای خواندن کاراکتر از صفحه کلید فراهم می‏کند، اما بایوس دارای تسهیلات بهتری برای این کار است. از این گذشته تعداد زیادی متغیر در رابطه با کیبرد در بخش داده‏ای بایوس وجود دارد که شما می‏توانید از آنها استفاده کنید. به طور کلی اگر شما نخواهید از تسهیلات ورودی/خروجی DOS استفاده کنید، استفاده از توابع بایوس برای خواندن کیبرد انعطاف پذیری بیشتری را فراهم می‏کند.


برای فراخوانی توابع BIOS از INT 16h استفاده می‏شود. بایوس توابعی را در رابطه با کیبرد فراهم می‏کند. که اونا رو اتچ میکنم

amin joon
شنبه 10 دی 1384, 12:57 عصر
بایوس توابع زیر را در رابطه با کیبرد فراهم می‏کند.


Function#:
0
input:
--
output:
al- ASCII character
ah- scan code
description:
Read character. Reads next available character from the system's type ahead buffer. Wait for a keystroke if the buffer is empty.

Function#:
1
input:
-
output:
ZF- Set if no key.
ZF- Clear if key available.
al- ASCII code
ah- scan code
description:
Checks to see if a character is available in the type ahead buffer. Sets the zero flag if not key is available, clears the zero flag if a key is available. If there is an available key, this function returns the ASCII and scan code value in ax. The value in ax is undefined if no key is available.

Function#:
2
input:
-
output:
al- shift flags
description:
Returns the current status of the shift flags in al. The shift flags are defined as follows: ʍ bit 7: Insert toggle bit 6: Capslock toggle bit 5: Numlock toggle bit 4: Scroll lock toggle bit 3: Alt key is down bit 2: Ctrl key is down bit 1: Left shift key is down bit 0: Right shift key is down

Function#:
3
input:
al = 5 bh = 0, 1, 2, 3 for 1/4, 1/2, 3/4, or 1 second delay bl= 0..1Fh for 30/sec to 2/sec.
output:
-
description:
Set auto repeat rate. The bh register contains the amount of time to wait before starting the autorepeat operation, the bl register contains the autorepeat rate.

Function#:
5
input:
ch = scan code cl = ASCII code
output:
-
description:
Store keycode in buffer. This function stores the value in the cx register at the end of the type ahead buffer. Note that the scan code in ch doesn't have to correspond to the ASCII code appearing in cl. This routine will simply insert the data you provide into the system type ahead buffer.

Function#:
10h
input:
-
output:
al- ASCII character ah- scan code
description:
Read extended character. Like ah=0 call, except this one passes all key codes, the ah=0 call throws away codes that are not PC/XT compatible.

Function#:
11h
input:
-
output:
ZF- Set if no key. ZF- Clear if key available. al- ASCII code ah- scan code
description:
Like the ah=01h call except this one does not throw away keycodes that are not PC/XT compatible (i.e., the extra keys found on the 101 key keyboard).

Function#:
12h
input:
-
output:
al- shift flags ah- extended shift flags
description:
Returns the current status of the shift flags in ax. The shift flags are defined as follows: ʍ bit 15: SysReq key pressed bit 14: Capslock key currently down bit 13: Numlock key currently down bit 12: Scroll lock key currently down bit 11: Right alt key is down bit 10:Right ctrl key is down bit 9: Left alt key is down bit 8: Left ctrl key is down bit 7: Insert toggle bit 6: Capslock toggle bit 5: Numlock toggle bit 4: Scroll lock toggle bit 3: Either alt key is down (some machines, left only) bit 2: Either ctrl key is down bit 1: Left shift key is down bit 0: Right shift key is down


کد اسمبلی زیر نشان میدهد که چگونه میتوان INT 16h ای ایجاد کرد که تمام کارهای بالا را انجام دهد.





; INT16.ASM
;
; A short passive TSR that replaces the BIOS' int 16h handler.
; This routine demonstrates the function of each of the int 16h
; functions that a standard BIOS would provide.
;
; Note that this code does not patch into int 2Fh (multiplex interrupt)
; nor can you remove this code from memory except by rebooting.
; If you want to be able to do these two things (as well as check for
; a previous installation), see the chapter on resident programs. Such
; code was omitted from this program because of length constraints.
;
;
; cseg and EndResident must occur before the standard library segments!

cseg segment para public 'code'
cseg ends

; Marker segment, to find the end of the resident section.

EndResident segment para public 'Resident'
EndResident ends

.xlist
include stdlib.a
includelib stdlib.lib
.list


byp equ <byte ptr>

cseg segment para public 'code'
assume cs:cseg, ds:cseg

OldInt16 dword ?


; BIOS variables:

KbdFlags1 equ <ds:[17h]>
KbdFlags2 equ <ds:[18h]>
AltKpd equ <ds:[19h]>
HeadPtr equ <ds:[1ah]>
TailPtr equ <ds:[1ch]>
Buffer equ 1eh
EndBuf equ 3eh

KbdFlags3 equ <ds:[96h]>
KbdFlags4 equ <ds:[97h]>

incptr macro which
local NoWrap
add bx, 2
cmp bx, EndBuf
jb NoWrap
mov bx, Buffer
NoWrap: mov which, bx
endm


; MyInt16- This routine processes the int 16h function requests.
;
; AH Description
; -- ------------------------------------------------
; 00h Get a key from the keyboard, return code in AX.
; 01h Test for available key, ZF=1 if none, ZF=0 and
; AX contains next key code if key available.
; 02h Get shift status. Returns shift key status in AL.
; 03h Set Autorepeat rate. BH=0,1,2,3 (delay time in
; quarter seconds), BL=0..1Fh for 30 char/sec to
; 2 char/sec repeat rate.
; 05h Store scan code (in CX) in the type ahead buffer.
; 10h Get a key (same as 00h in this implementation).
; 11h Test for key (same as 01h).
; 12h Get extended key status. Returns status in AX.


MyInt16 proc far
test ah, 0EFh ;Check for 0h and 10h
je GetKey
cmp ah, 2 ;Check for 01h and 02h
jb TestKey
je GetStatus
cmp ah, 3 ;Check for AutoRpt function.
je SetAutoRpt
cmp ah, 5 ;Check for StoreKey function.
je StoreKey
cmp ah, 11h ;Extended test key opcode.
je TestKey
cmp ah, 12h ;Extended status call
je ExtStatus

; Well, it's a function we don't know about, so just return to the caller.

iret

; If the user specified ah=0 or ah=10h, come down here (we will not
; differentiate between extended and original PC getc calls).

GetKey: mov ah, 11h
int 16h ;See if key is available.
je GetKey ;Wait for keystroke.

push ds
push bx
mov ax, 40h
mov ds, ax
cli ;Critical region! Ints off.
mov bx, HeadPtr ;Ptr to next character.
mov ax, [bx] ;Get the character.
incptr HeadPtr ;Bump up HeadPtr
pop bx
pop ds
iret ;Restores interrupt flag.

; TestKey- Checks to see if a key is available in the keyboard buffer.
; We need to turn interrupts on here (so the kbd ISR can
; place a character in the buffer if one is pending).
; Generally, you would want to save the interrupt flag here.
; But BIOS always forces interrupts on, so there may be some
; programs out there that depend on this, so we won't "fix"
; this problem.
;
; Returns key status in ZF and AX. If ZF=1 then no key is
; available and the value in AX is indeterminate. If ZF=0
; then a key is available and AX contains the scan/ASCII
; code of the next available key. This call does not remove
; the next character from the input buffer.

TestKey: sti ;Turn on the interrupts.
push ds
push bx
mov ax, 40h
mov ds, ax
cli ;Critical region, ints off!
mov bx, HeadPtr
mov ax, [bx] ;BIOS returns avail keycode.
cmp bx, TailPtr ;ZF=1, if empty buffer
pop bx
pop ds
sti ;Inst back on.
retf 2 ;Pop flags (ZF is important!)


; The GetStatus call simply returns the KbdFlags1 variable in AL.

GetStatus: push ds
mov ax, 40h
mov ds, ax
mov al, KbdFlags1 ;Just return Std Status.
pop ds
iret


; StoreKey- Inserts the value in CX into the type ahead buffer.

StoreKey: push ds
push bx
mov ax, 40h
mov ds, ax
cli ;Ints off, critical region.
mov bx, TailPtr ;Address where we can put
push bx ; next key code.
mov [bx], cx ;Store the key code away.
incptr TailPtr ;Move on to next entry in buf.
cmp bx, HeadPtr ;Data overrun?
jne StoreOkay ;If not, jump, if so
pop TailPtr ; ignore key entry.
sub sp, 2 ;So stack matches alt path.
StoreOkay: add sp, 2 ;Remove junk data from stk.
pop bx
pop ds
iret ;Restores interrupts.


; ExtStatus- Retrieve the extended keyboard status and return it in
; AH, also returns the standard keyboard status in AL.

ExtStatus: push ds
mov ax, 40h
mov ds, ax

mov ah, KbdFlags2
and ah, 7Fh ;Clear final sysreq field.
test ah, 100b ;Test cur sysreq bit.
je NoSysReq ;Skip if it's zero.
or ah, 80h ;Set final sysreq bit.
NoSysReq:
and ah, 0F0h ;Clear alt/ctrl bits.
mov al, KbdFlags3
and al, 1100b ;Grab rt alt/ctrl bits.
or ah, al ;Merge into AH.
mov al, KbdFlags2
and al, 11b ;Grab left alt/ctrl bits.
or ah, al ;Merge into AH.

mov al, KbdFlags1 ;AL contains normal flags.
pop ds
iret

; SetAutoRpt- Sets the autorepeat rate. On entry, bh=0, 1, 2, or 3 (delay
; in 1/4 sec before autorepeat starts) and bl=0..1Fh (repeat
; rate, about 2:1 to 30:1 (chars:sec).

SetAutoRpt: push cx
push bx

mov al, 0ADh ;Disable kbd for now.
call SetCmd

and bh, 11b ;Force into proper range.
mov cl, 5
shl bh, cl ;Move to final position.
and bl, 1Fh ;Force into proper range.
or bh, bl ;8042 command data byte.
mov al, 0F3h ;8042 set repeat rate cmd.
call SendCmd ;Send the command to 8042.
mov al, bh ;Get parameter byte
call SendCmd ;Send parameter to the 8042.

mov al, 0AEh ;Reenable keyboard.
call SetCmd
mov al, 0F4h ;Restart kbd scanning.
call SendCmd

pop bx
pop cx
iret

MyInt16 endp



; SetCmd- Sends the command byte in the AL register to the 8042
; keyboard microcontroller chip (command register at
; port 64h).

SetCmd proc near
push cx
push ax ;Save command value.
cli ;Critical region, no ints now.

; Wait until the 8042 is done processing the current command.

xor cx, cx ;Allow 65,536 times thru loop.
Wait4Empty: in al, 64h ;Read keyboard status register.
test al, 10b ;Input buffer full?
loopnz Wait4Empty ;If so, wait until empty.

; Okay, send the command to the 8042:

pop ax ;Retrieve command.
out 64h, al
sti ;Okay, ints can happen again.
pop cx
ret
SetCmd endp




; SendCmd- The following routine sends a command or data byte to the
; keyboard data port (port 60h).

SendCmd proc near
push ds
push bx
push cx
mov cx, 40h
mov ds, cx
mov bx, ax ;Save data byte

mov bh, 3 ;Retry cnt.
RetryLp: cli ;Disable ints while accessing HW.

; Clear the Error, Acknowledge received, and resend received flags
; in KbdFlags4

and byte ptr KbdFlags4, 4fh

; Wait until the 8042 is done processing the current command.

xor cx, cx ;Allow 65,536 times thru loop.
Wait4Empty: in al, 64h ;Read keyboard status register.
test al, 10b ;Input buffer full?
loopnz Wait4Empty ;If so, wait until empty.

; Okay, send the data to port 60h

mov al, bl
out 60h, al
sti ;Allow interrupts now.

; Wait for the arrival of an acknowledgement from the keyboard ISR:

xor cx, cx ;Wait a long time, if need be.
Wait4Ack: test byp KbdFlags4, 10 ;Acknowledge received bit.
jnz GotAck
loop Wait4Ack
dec bh ;Do a retry on this guy.
jne RetryLp

; If the operation failed after 3 retries, set the error bit and quit.

or byp KbdFlags4, 80h ;Set error bit.

GotAck: pop cx
pop bx
pop ds
ret
SendCmd endp



Main proc

mov ax, cseg
mov ds, ax

print
byte "INT 16h Replacement",cr,lf
byte "Installing....",cr,lf,0

; Patch into the INT 9 and INT 16 interrupt vectors. Note that the
; statements above have made cseg the current data segment,
; so we can store the old INT 9 and INT 16 values directly into
; the OldInt9 and OldInt16 variables.

cli ;Turn off interrupts!
mov ax, 0
mov es, ax
mov ax, es:[16h*4]
mov word ptr OldInt16, ax
mov ax, es:[16h*4 + 2]
mov word ptr OldInt16+2, ax
mov es:[16h*4], offset MyInt16
mov es:[16h*4+2], cs
sti ;Okay, ints back on.


; We're hooked up, the only thing that remains is to terminate and
; stay resident.

print
byte "Installed.",cr,lf,0

mov ah, 62h ;Get this program's PSP
int 21h ; value.

mov dx, EndResident ;Compute size of program.
sub dx, bx
mov ax, 3100h ;DOS TSR command.
int 21h
Main endp
cseg ends

sseg segment para stack 'stack'
stk db 1024 dup ("stack ")
sseg ends

zzzzzzseg segment para public 'zzzzzz'
LastBytes db 16 dup (?)
zzzzzzseg ends
end Main

amin joon
شنبه 10 دی 1384, 13:00 عصر
روتین سرویس وقفه‏ی کیبرد


INT 16h یک رابط بین برنامه‏های کاربردی و کیبرد است؛ وINT 9h یک رابط بین سخت‏افزار کیبرد و INT 16h است. پردازش وقفه‏های سخت افزاری کیبرد، تبدیل کد اسکن ورودی به ترکیبی از کد اسکی و کد اسکن وقرار دادن آن در بافر صفحه کلید و پردازش بقیه‏‏ی پیام هایی که کیبرد تولید می‏کند از وظایف INT 9h است
برای تبدیل کد اسکن به ترکیبی از کد اسکی و کد اسکن، INT 9h باید وضعیت کلیدهای تغییر دهنده را نگه دارد. INT 9h برای تبدیل کد اسکن به اسکی از یک جدول استفاده می‏کند که بر اساس کلیدهای تغییر دهنده تنظیم شده. نکته‏ی مهم دیگر این است که گرداننده‏ی INT 9h باید کلیدهای ویژه مانند ctrl+alt+del (بوت) وprtscr را نیز اداره کند. برنامه‏ی مقیم در حافظه که در پایین آمده، یک گرداننده‏ی ساده برای وقفه‏ی 9h را ایجاد می‏کند که تمام تکنیک‏هایی که برای برنامه نویسی کیبرد لازم است را در بر دارد.



; INT9.ASM
;
; A short TSR to provide a driver for the keyboard hardware interrupt.
;
; Note that this code does not patch into int 2Fh (multiplex interrupt)
; nor can you remove this code from memory except by rebooting.
; If you want to be able to do these two things (as well as check for
; a previous installation), see the chapter on resident programs. Such
; code was omitted from this program because of length constraints.
;
;
; cseg and EndResident must occur before the standard library segments!

cseg segment para public 'code'
OldInt9 dword ?
cseg ends

; Marker segment, to find the end of the resident section.

EndResident segment para public 'Resident'
EndResident ends

.xlist
include stdlib.a
includelib stdlib.lib
.list


NumLockScan equ 45h
ScrlLockScan equ 46h
CapsLockScan equ 3ah
CtrlScan equ 1dh
AltScan equ 38h
RShiftScan equ 36h
LShiftScan equ 2ah
InsScanCode equ 52h
DelScanCode equ 53h

; Bits for the various modifier keys

RShfBit equ 1
LShfBit equ 2
CtrlBit equ 4
AltBit equ 8
SLBit equ 10h
NLBit equ 20h
CLBit equ 40h
InsBit equ 80h


KbdFlags equ <byte ptr ds:[17h]>
KbdFlags2 equ <byte ptr ds:[18h]>
KbdFlags3 equ <byte ptr ds:[96h]>
KbdFlags4 equ <byte ptr ds:[97h]>

byp equ <byte ptr>


cseg segment para public 'code'
assume ds:nothing

; Scan code translation table.
; The incoming scan code from the keyboard selects a row.
; The modifier status selects the column.
; The word at the intersection of the two is the scan/ASCII code to
; put into the PC's type ahead buffer.
; If the value fetched from the table is zero, then we do not put the
; character into the type ahead buffer.
;
; norm shft ctrl alt num caps shcap shnum

ScanXlat word 0000h, 0000h, 0000h, 0000h, 0000h, 0000h, 0000h, 0000h
word 011bh, 011bh, 011bh, 011bh, 011bh, 011bh, 011bh, 011bh ;ESC
word 0231h, 0231h, 0000h, 7800h, 0231h, 0231h, 0231h, 0321h ;1 !
word 0332h, 0340h, 0300h, 7900h, 0332h, 0332h, 0332h, 0332h ;2 @
word 0433h, 0423h, 0000h, 7a00h, 0433h, 0433h, 0423h, 0423h ;3 #
word 0534h, 0524h, 0000h, 7b00h, 0534h, 0534h, 0524h, 0524h ;4 $
word 0635h, 0625h, 0000h, 7c00h, 0635h, 0635h, 0625h, 0625h ;5 %
word 0736h, 075eh, 071eh, 7d00h, 0736h, 0736h, 075eh, 075eh ;6 ^

word 0837h, 0826h, 0000h, 7e00h, 0837h, 0837h, 0826h, 0826h ;7 &
word 0938h, 092ah, 0000h, 7f00h, 0938h, 0938h, 092ah, 092ah ;8 *
word 0a39h, 0a28h, 0000h, 8000h, 0a39h, 0a39h, 0a28h, 0a28h ;9 (
word 0b30h, 0b29h, 0000h, 8100h, 0b30h, 0b30h, 0b29h, 0b29h ;0 )
word 0c2dh, 0c5fh, 0000h, 8200h, 0c2dh, 0c2dh, 0c5fh, 0c5fh ;- _
word 0d3dh, 0d2bh, 0000h, 8300h, 0d3dh, 0d3dh, 0d2bh, 0d2bh ;= +
word 0e08h, 0e08h, 0e7fh, 0000h, 0e08h, 0e08h, 0e08h, 0e08h ;bksp
word 0f09h, 0f00h, 0000h, 0000h, 0f09h, 0f09h, 0f00h, 0f00h ;Tab

; norm shft ctrl alt num caps shcap shnum
word 1071h, 1051h, 1011h, 1000h, 1071h, 1051h, 1051h, 1071h ;Q
word 1177h, 1057h, 1017h, 1100h, 1077h, 1057h, 1057h, 1077h ;W
word 1265h, 1245h, 1205h, 1200h, 1265h, 1245h, 1245h, 1265h ;E
word 1372h, 1352h, 1312h, 1300h, 1272h, 1252h, 1252h, 1272h ;R
word 1474h, 1454h, 1414h, 1400h, 1474h, 1454h, 1454h, 1474h ;T
word 1579h, 1559h, 1519h, 1500h, 1579h, 1559h, 1579h, 1559h ;Y
word 1675h, 1655h, 1615h, 1600h, 1675h, 1655h, 1675h, 1655h ;U
word 1769h, 1749h, 1709h, 1700h, 1769h, 1749h, 1769h, 1749h ;I

word 186fh, 184fh, 180fh, 1800h, 186fh, 184fh, 186fh, 184fh ;O
word 1970h, 1950h, 1910h, 1900h, 1970h, 1950h, 1970h, 1950h ;P
word 1a5bh, 1a7bh, 1a1bh, 0000h, 1a5bh, 1a5bh, 1a7bh, 1a7bh ;[ {
word 1b5dh, 1b7dh, 1b1dh, 0000h, 1b5dh, 1b5dh, 1b7dh, 1b7dh;] }
word 1c0dh, 1c0dh, 1c0ah, 0000h, 1c0dh, 1c0dh, 1c0ah, 1c0ah ;enter
word 1d00h, 1d00h, 1d00h, 1d00h, 1d00h, 1d00h, 1d00h, 1d00h ;ctrl
word 1e61h, 1e41h, 1e01h, 1e00h, 1e61h, 1e41h, 1e61h, 1e41h ;A
word 1f73h, 1f5eh, 1f13h, 1f00h, 1f73h, 1f53h, 1f73h, 1f53h ;S

; norm shft ctrl alt num caps shcap shnum
word 2064h, 2044h, 2004h, 2000h, 2064h, 2044h, 2064h, 2044h ;D
word 2166h, 2146h, 2106h, 2100h, 2166h, 2146h, 2166h, 2146h ;F
word 2267h, 2247h, 2207h, 2200h, 2267h, 2247h, 2267h, 2247h ;G
word 2368h, 2348h, 2308h, 2300h, 2368h, 2348h, 2368h, 2348h ;H
word 246ah, 244ah, 240ah, 2400h, 246ah, 244ah, 246ah, 244ah ;J
word 256bh, 254bh, 250bh, 2500h, 256bh, 254bh, 256bh, 254bh ;K
word 266ch, 264ch, 260ch, 2600h, 266ch, 264ch, 266ch, 264ch ;L
word 273bh, 273ah, 0000h, 0000h, 273bh, 273bh, 273ah, 273ah ;; :

word 2827h, 2822h, 0000h, 0000h, 2827h, 2827h, 2822h, 2822h ;' "
word 2960h, 297eh, 0000h, 0000h, 2960h, 2960h, 297eh, 297eh ;` ~
word 2a00h, 2a00h, 2a00h, 2a00h, 2a00h, 2a00h, 2a00h, 2a00h ;LShf
word 2b5ch, 2b7ch, 2b1ch, 0000h, 2b5ch, 2b5ch, 2b7ch, 2b7ch ;\ |
word 2c7ah, 2c5ah, 2c1ah, 2c00h, 2c7ah, 2c5ah, 2c7ah, 2c5ah ;Z
word 2d78h, 2d58h, 2d18h, 2d00h, 2d78h, 2d58h, 2d78h, 2d58h;X
word 2e63h, 2e43h, 2e03h, 2e00h, 2e63h, 2e43h, 2e63h, 2e43h ;C
word 2f76h, 2f56h, 2f16h, 2f00h, 2f76h, 2f56h, 2f76h, 2f56h ;V

; norm shft ctrl alt num caps shcap shnum
word 3062h, 3042h, 3002h, 3000h, 3062h, 3042h, 3062h, 3042h ;B
word 316eh, 314eh, 310eh, 3100h, 316eh, 314eh, 316eh, 314eh ;N
word 326dh, 324dh, 320dh, 3200h, 326dh, 324dh, 326dh, 324dh ;M
word 332ch, 333ch, 0000h, 0000h, 332ch, 332ch, 333ch, 333ch ;, <
word 342eh, 343eh, 0000h, 0000h, 342eh, 342eh, 343eh, 343eh ;. >
word 352fh, 353fh, 0000h, 0000h, 352fh, 352fh, 353fh, 353fh ;/ ?
word 3600h, 3600h, 3600h, 3600h, 3600h, 3600h, 3600h, 3600h ;rshf
word 372ah, 0000h, 3710h, 0000h, 372ah, 372ah, 0000h, 0000h ;* PS

word 3800h, 3800h, 3800h, 3800h, 3800h, 3800h, 3800h, 3800h ;alt
word 3920h, 3920h, 3920h, 0000h, 3920h, 3920h, 3920h, 3920h ;spc
word 3a00h, 3a00h, 3a00h, 3a00h, 3a00h, 3a00h, 3a00h, 3a00h ;caps
word 3b00h, 5400h, 5e00h, 6800h, 3b00h, 3b00h, 5400h, 5400h ;F1
word 3c00h, 5500h, 5f00h, 6900h, 3c00h, 3c00h, 5500h, 5500h ;F2
word 3d00h, 5600h, 6000h, 6a00h, 3d00h, 3d00h, 5600h, 5600h ;F3
word 3e00h, 5700h, 6100h, 6b00h, 3e00h, 3e00h, 5700h, 5700h ;F4
word 3f00h, 5800h, 6200h, 6c00h, 3f00h, 3f00h, 5800h, 5800h ;F5

; norm shft ctrl alt num caps shcap shnum
word 4000h, 5900h, 6300h, 6d00h, 4000h, 4000h, 5900h, 5900h ;F6
word 4100h, 5a00h, 6400h, 6e00h, 4100h, 4100h, 5a00h, 5a00h ;F7
word 4200h, 5b00h, 6500h, 6f00h, 4200h, 4200h, 5b00h, 5b00h ;F8
word 4300h, 5c00h, 6600h, 7000h, 4300h, 4300h, 5c00h, 5c00h ;F9
word 4400h, 5d00h, 6700h, 7100h, 4400h, 4400h, 5d00h, 5d00h ;F10
word 4500h, 4500h, 4500h, 4500h, 4500h, 4500h, 4500h, 4500h ;num
word 4600h, 4600h, 4600h, 4600h, 4600h, 4600h, 4600h, 4600h ;scrl
word 4700h, 4737h, 7700h, 0000h, 4737h, 4700h, 4737h, 4700h ;home

word 4800h, 4838h, 0000h, 0000h, 4838h, 4800h, 4838h, 4800h ;up
word 4900h, 4939h, 8400h, 0000h, 4939h, 4900h, 4939h, 4900h ;pgup
word 4a2dh, 4a2dh, 0000h, 0000h, 4a2dh, 4a2dh, 4a2dh, 4a2dh ;-
word 4b00h, 4b34h, 7300h, 0000h, 4b34h, 4b00h, 4b34h, 4b00h ;left
word 4c00h, 4c35h, 0000h, 0000h, 4c35h, 4c00h, 4c35h, 4c00h ;Center
word 4d00h, 4d36h, 7400h, 0000h, 4d36h, 4d00h, 4d36h, 4d00h ;right
word 4e2bh, 4e2bh, 0000h, 0000h, 4e2bh, 4e2bh, 4e2bh, 4e2bh ;+
word 4f00h, 4f31h, 7500h, 0000h, 4f31h, 4f00h, 4f31h, 4f00h ;end

; norm shft ctrl alt num caps shcap shnum
word 5000h, 5032h, 0000h, 0000h, 5032h, 5000h, 5032h, 5000h ;down
word 5100h, 5133h, 7600h, 0000h, 5133h, 5100h, 5133h, 5100h ;pgdn
word 5200h, 5230h, 0000h, 0000h, 5230h, 5200h, 5230h, 5200h ;ins
word 5300h, 532eh, 0000h, 0000h, 532eh, 5300h, 532eh, 5300h ;del
word 0,0,0,0,0,0,0,0 ; --
word 0,0,0,0,0,0,0,0 ; --
word 0,0,0,0,0,0,0,0 ; --
word 5700h, 0000h, 0000h, 0000h, 5700h, 5700h, 0000h, 0000h ;F11

word 5800h, 0000h, 0000h, 0000h, 5800h, 5800h, 0000h, 0000h ;F12



;************************************************* ***************************
;
; AL contains keyboard scan code.

PutInBuffer proc near
push ds
push bx

mov bx, 40h ;Point ES at the BIOS
mov ds, bx ; variables.

; If the current scan code is E0 or E1, we need to take note of this fact
; so that we can properly process cursor keys.

cmp al, 0e0h
jne TryE1
or KbdFlags3, 10b ;Set E0 flag
and KbdFlags3, 0FEh ;Clear E1 flag
jmp Done

TryE1: cmp al, 0e1h
jne DoScan
or KbdFlags3, 1 ;Set E1 flag
and KbdFlags3, 0FDh ;Clear E0 Flag
jmp Done


; Before doing anything else, see if this is Ctrl-Alt-Del:

DoScan: cmp al, DelScanCode
jnz TryIns
mov bl, KbdFlags
and bl, AltBit or CtrlBit ;Alt = bit 3, ctrl = bit 2
cmp bl, AltBit or CtrlBit
jne DoPIB
mov word ptr ds:[72h], 1234h ;Warm boot flag.
jmp dword ptr cs:RebootAdrs ;REBOOT Computer

RebootAdrs dword 0ffff0000h ;Reset address.


; Check for the INS key here. This one needs to toggle the ins bit
; in the keyboard flags variables.

TryIns: cmp al, InsScanCode
jne TryInsUp
or KbdFlags2, InsBit ;Note INS is down.
jmp doPIB ;Pass on INS key.

TryInsUp: cmp al, InsScanCode+80h ;INS up scan code.
jne TryLShiftDn
and KbdFlags2, not InsBit ;Note INS is up.
xor KbdFlags, InsBit ;Toggle INS bit.
jmp QuitPIB

; Handle the left and right shift keys down here.

TryLShiftDn: cmp al, LShiftScan
jne TryLShiftUp
or KbdFlags, LShfBit ;Note that the left
jmp QuitPIB ; shift key is down.

TryLShiftUp: cmp al, LShiftScan+80h
jne TryRShiftDn
and KbdFlags, not LShfBit ;Note that the left
jmp QuitPIB ; shift key is up.


TryRShiftDn: cmp al, RShiftScan
jne TryRShiftUp
or KbdFlags, RShfBit ;Right shf is down.
jmp QuitPIB

TryRShiftUp: cmp al, RShiftScan+80h
jne TryAltDn
and KbdFlags, not RShfBit ;Right shf is up.
jmp QuitPIB

; Handle the ALT key down here.

TryAltDn: cmp al, AltScan
jne TryAltUp
or KbdFlags, AltBit ;Alt key is down.
GotoQPIB: jmp QuitPIB

TryAltUp: cmp al, AltScan+80h
jne TryCtrlDn
and KbdFlags, not AltBit ;Alt key is up.
jmp DoPIB


; Deal with the control key down here.

TryCtrlDn: cmp al, CtrlScan
jne TryCtrlUp
or KbdFlags, CtrlBit ;Ctrl key is down.
jmp QuitPIB

TryCtrlUp: cmp al, CtrlScan+80h
jne TryCapsDn
and KbdFlags, not CtrlBit ;Ctrl key is up.
jmp QuitPIB

; Deal with the CapsLock key down here.

TryCapsDn: cmp al, CapsLockScan
jne TryCapsUp
or KbdFlags2, CLBit ;Capslock is down.
xor KbdFlags, CLBit ;Toggle capslock.
jmp QuitPIB

TryCapsUp: cmp al, CapsLockScan+80h
jne TrySLDn
and KbdFlags2, not CLBit ;Capslock is up.
call SetLEDs
jmp QuitPIB

; Deal with the Scroll Lock key down here.

TrySLDn: cmp al, ScrlLockScan
jne TrySLUp
or KbdFlags2, SLBit ;Scrl lock is down.
xor KbdFlags, SLBit ;Toggle scrl lock.
jmp QuitPIB

TrySLUp: cmp al, ScrlLockScan+80h
jne TryNLDn
and KbdFlags2, not SLBit ;Scrl lock is up.
call SetLEDs
jmp QuitPIB

; Handle the NumLock key down here.


TryNLDn: cmp al, NumLockScan
jne TryNLUp
or KbdFlags2, NLBit ;Numlock is down.
xor KbdFlags, NLBit ;Toggle numlock.
jmp QuitPIB

TryNLUp: cmp al, NumLockScan+80h
jne DoPIB
and KbdFlags2, not NLBit ;Numlock is up.
call SetLEDs
jmp QuitPIB



; Handle all the other keys here:

DoPIB: test al, 80h ;Ignore other up keys.
jnz QuitPIB

; If the H.O. bit is set at this point, we'd best only have a zero in AL.
; Otherwise, this is an up code which we can safely ignore.

call Convert
test ax, ax ;Chk for bad code.
je QuitPIB

PutCharInBuf: push cx
mov cx, ax
mov ah, 5 ;Store scan code into
int 16h ; type ahead buffer.
pop cx

QuitPIB: and KbdFlags3, 0FCh ;E0, E1 not last code.

Done: pop bx
pop ds
ret
PutInBuffer endp




;************************************************* ***************************
;
; Convert- AL contains a PC Scan code. Convert it to an ASCII char/Scan
; code pair and return the result in AX. This code assumes
; that DS points at the BIOS variable space (40h).

Convert proc near
push bx

test al, 80h ;See if up code
jz DownScanCode
mov ah, al
mov al, 0
jmp CSDone

; Okay, we've got a down key. But before going on, let's see if we've
; got an ALT-Keypad sequence.

DownScanCode: mov bh, 0
mov bl, al
shl bx, 1 ;Multiply by eight to compute
shl bx, 1 ; row index index the scan
shl bx, 1 ; code xlat table

; Compute modifier index as follows:
;
; if alt then modifier = 3

test KbdFlags, AltBit
je NotAlt
add bl, 3
jmp DoConvert

; if ctrl, then modifier = 2

NotAlt: test KbdFlags, CtrlBit
je NotCtrl
add bl, 2
jmp DoConvert

; Regardless of the shift setting, we've got to deal with numlock
; and capslock. Numlock is only a concern if the scan code is greater
; than or equal to 47h. Capslock is only a concern if the scan code
; is less than this.

NotCtrl: cmp al, 47h
jb DoCapsLk
test KbdFlags, NLBit ;Test Numlock bit
je NoNumLck
test KbdFlags, LShfBit or RShfBit ;Check l/r shift.
je NumOnly
add bl, 7 ;Numlock and shift.
jmp DoConvert

NumOnly: add bl, 4 ;Numlock only.
jmp DoConvert

; If numlock is not active, see if a shift key is:

NoNumLck: test KbdFlags, LShfBit or RShfBit ;Check l/r shift.
je DoConvert ;normal if no shift.
add bl, 1
jmp DoConvert

; If the scan code's value is below 47h, we need to check for capslock.

DoCapsLk: test KbdFlags, CLBit ;Chk capslock bit
je DoShift
test KbdFlags, LShfBit or RShfBit ;Chk for l/r shift
je CapsOnly
add bl, 6 ;Shift and capslock.
jmp DoConvert

CapsOnly: add bl, 5 ;Capslock
jmp DoConvert

; Well, nothing else is active, check for just a shift key.

DoShift: test KbdFlags, LShfBit or RShfBit ;l/r shift.
je DoConvert
add bl, 1 ;Shift

DoConvert: shl bx, 1 ;Word array
mov ax, ScanXlat[bx]
CSDone: pop bx
ret
Convert endp




; SetCmd- Sends the command byte in the AL register to the 8042
; keyboard microcontroller chip (command register at
; port 64h).

SetCmd proc near
push cx
push ax ;Save command value.
cli ;Critical region, no ints now.

; Wait until the 8042 is done processing the current command.

xor cx, cx ;Allow 65,536 times thru loop.
Wait4Empty: in al, 64h ;Read keyboard status register.
test al, 10b ;Input buffer full?
loopnz Wait4Empty ;If so, wait until empty.

; Okay, send the command to the 8042:

pop ax ;Retrieve command.
out 64h, al
sti ;Okay, ints can happen again.
pop cx
ret
SetCmd endp



; SendCmd- The following routine sends a command or data byte to the
; keyboard data port (port 60h).

SendCmd proc near
push ds
push bx
push cx
mov cx, 40h
mov ds, cx
mov bx, ax ;Save data byte

mov bh, 3 ;Retry cnt.
RetryLp: cli ;Disable ints while accessing HW.

; Clear the Error, Acknowledge received, and resend received flags
; in KbdFlags4

and byte ptr KbdFlags4, 4fh

; Wait until the 8042 is done processing the current command.

xor cx, cx ;Allow 65,536 times thru loop.
Wait4Empty: in al, 64h ;Read keyboard status register.
test al, 10b ;Input buffer full?
loopnz Wait4Empty ;If so, wait until empty.

; Okay, send the data to port 60h

mov al, bl
out 60h, al
sti ;Allow interrupts now.

; Wait for the arrival of an acknowledgement from the keyboard ISR:

xor cx, cx ;Wait a long time, if need be.
Wait4Ack: test byp KbdFlags4,10h ;Acknowledge received bit.
jnz GotAck
loop Wait4Ack
dec bh ;Do a retry on this guy.
jne RetryLp

; If the operation failed after 3 retries, set the error bit and quit.

or byp KbdFlags4,80h ;Set error bit.

GotAck: pop cx
pop bx
pop ds
ret
SendCmd endp




; SetLEDs- Updates the KbdFlags4 LED bits from the KbdFlags
; variable and then transmits new flag settings to
; the keyboard.

SetLEDs proc near
push ax
push cx
mov al, KbdFlags
mov cl, 4
shr al, cl
and al, 111b
and KbdFlags4, 0F8h ;Clear LED bits.
or KbdFlags4, al ;Mask in new bits.
mov ah, al ;Save LED bits.

mov al, 0ADh ;Disable kbd for now.
call SetCmd

mov al, 0EDh ;8042 set LEDs cmd.
call SendCmd ;Send the command to 8042.
mov al, ah ;Get parameter byte
call SendCmd ;Send parameter to the 8042.

mov al, 0AEh ;Reenable keyboard.
call SetCmd
mov al, 0F4h ;Restart kbd scanning.
call SendCmd
pop cx
pop ax
ret
SetLEDs endp


; MyInt9- Interrupt service routine for the keyboard hardware
; interrupt.

MyInt9 proc far
push ds
push ax
push cx

mov ax, 40h
mov ds, ax

mov al, 0ADh ;Disable keyboard
call SetCmd
cli ;Disable interrupts.
xor cx, cx
Wait4Data: in al, 64h ;Read kbd status port.
test al, 10b ;Data in buffer?
loopz Wait4Data ;Wait until data available.
in al, 60h ;Get keyboard data.
cmp al, 0EEh ;Echo response?
je QuitInt9
cmp al, 0FAh ;Acknowledge?
jne NotAck
or KbdFlags4, 10h ;Set ack bit.
jmp QuitInt9

NotAck: cmp al, 0FEh ;Resend command?
jne NotResend
or KbdFlags4, 20h ;Set resend bit.
jmp QuitInt9

; Note: other keyboard controller commands all have their H.O. bit set
; and the PutInBuffer routine will ignore them.

NotResend: call PutInBuffer ;Put in type ahead buffer.

QuitInt9: mov al, 0AEh ;Reenable the keyboard
call SetCmd

mov al, 20h ;Send EOI (end of interrupt)
out 20h, al ; to the 8259A PIC.
pop cx
pop ax
pop ds
iret
MyInt9 endp



Main proc
assume ds:cseg

mov ax, cseg
mov ds, ax

print
byte "INT 9 Replacement",cr,lf
byte "Installing....",cr,lf,0

; Patch into the INT 9 interrupt vector. Note that the
; statements above have made cseg the current data segment,
; so we can store the old INT 9 value directly into
; the OldInt9 variable.

cli ;Turn off interrupts!
mov ax, 0
mov es, ax
mov ax, es:[9*4]
mov word ptr OldInt9, ax
mov ax, es:[9*4 + 2]
mov word ptr OldInt9+2, ax
mov es:[9*4], offset MyInt9
mov es:[9*4+2], cs
sti ;Okay, ints back on.


; We're hooked up, the only thing that remains is to terminate and
; stay resident.

print
byte "Installed.",cr,lf,0

mov ah, 62h ;Get this program's PSP
int 21h ; value.

mov dx, EndResident ;Compute size of program.
sub dx, bx
mov ax, 3100h ;DOS TSR command.
int 21h
Main endp
cseg ends

sseg segment para stack 'stack'
stk byte 1024 dup ("stack ")
sseg ends

zzzzzzseg segment para public 'zzzzzz'
LastBytes db 16 dup (?)
zzzzzzseg ends
end Main

amin joon
شنبه 10 دی 1384, 13:11 عصر
البته قبل از خواندن موارد بالا بهتر بود که مقدمات سخت افزار صفحه کلید رو رو سایت میذاشتم....که البته همونطور که گفتم دکمه ی attatch سایت حذف شده....بعدا اون رو میفرستم

اگه سوالی در باره ی کدها دارید ...در خدمتم.
امیدوارم مفید باشه

Iran-PC
شنبه 10 دی 1384, 21:37 عصر
آفرین:تشویق::تشویق::تشویق::ت ویق::تشویق:

خیلی خیلی ممنون

خیلی عالی بود.
ادامه لطفا.


راستی
سی دی رام های من نا پدید شدند.
کسی نمیدونه چطور میشه درستش کرد؟

amin joon
یک شنبه 11 دی 1384, 18:09 عصر
مثل اینکه درست شده



راستی
سی دی رام های من نا پدید شدند.
کسی نمیدونه چطور میشه درستش کرد؟

بگردی پیداش میکنی :لبخند::چشمک::لبخند::چشمک::لب ند::چشمک::لبخند:

این فایلی رو که attach کردم در مورد مبانی کیبرد،روش کار وقفه ی 9، پرتهای کیبرد و روش کار با این پرتها است همچنین یه مثال جالب در باره ی کار با led های کیبرد هم داره....

مطالب مفیدی داره

موفق باشید

aakh1361
یک شنبه 02 بهمن 1384, 13:28 عصر
امین جون بسیار عالی و کامل بود
تشکر http://qsmile.com/qsimages/72.gif

aakh1361
یک شنبه 02 بهمن 1384, 13:32 عصر
یک سوال هم داشتم و اون اینه که چطور با فرستادن عدد (کد دستورات) به پورت کیبورد یشه A20 رو فعال کرد
نکته : در واقع بعد از فعال شدن (بعد از ورور به مد حفاظت شده) شما می تونید با فعال کردن A20 به چهار گیگا بایت ححافظه دسترسی داشته باشید و اگر A20 فعال نشه با اینکه در مود حفاظت شده هستید و لی نمی تونید
به چهار گیگا بایت دسترسی داشته باشید و محدود به همون یک مگابایت هستید
وقتی که من سورس سیستم عامل ها رو نگاه می کردم دیدم برای فعال کردن A20 دستوراتی رو به پورت کیبرد 60 و 64 می فرستند اگر در این زمینه اطلاعاتی دارید لطفا دریغ نکنید

mah.yar
یک شنبه 09 بهمن 1384, 06:54 صبح
سلام
یه سوال :
چه طور میشه با استفاده از توابع وقفه 01برنامه‎ای نوشت که هر کلیدی رو فشار میدیم 2بار تو خروجی نشون بده.البته به همراه تابع09.:متعجب:

ehsannn
یک شنبه 09 بهمن 1384, 17:19 عصر
کمک
من باید تا فردا یعنی دهم بهمن یه پروژه بدم:
هر حرفی که تایپ کردی دو بار تو مانیتور نشون بده

ehsannn
یک شنبه 09 بهمن 1384, 17:20 عصر
کمک
من باید تا فردا یعنی دهم بهمن یه پروژه بدم:
هر حرفی که تایپ کردی دو بار تو مانیتور نشون بده

amin joon
یک شنبه 09 بهمن 1384, 23:40 عصر
سلام

در مورد a20 راستش چیزی نشنیدم............... من در واقع این مطالب رو به خاطر پروژه ی درس اسمبلی که نوشتن یک فارسی ساز تحت محیط داس بود مطالعه کردم........
ولی اگه مشکل شما ارسال مقدار به یک پرت خاص هست ، با استفاده از کدی که بالا هست میتونید مشکلتون رو حل کنید.....فقط چندتا نکته در ارسال یک مقدار به پرت کیبرد وجود داره( مثلا بررسی بافر ورودی و خروجی) که توی فایلی که اتچ کردم در این مورد توضیح دادم.........اگه مشکل خاصی بود...در خدمت هستم............خلاصه شرمنده...

در مورد سوال دوم باید بگم که وقفه ی 1h زمانی اجرا میشه که بیت trap یک شده باشه یعنی وقتی که برنامه بصورتstep by step اجرا بشه..... نکته ی دیگه این که وقفه ی 01h در حالت پیشفرض تنها باعث اجرای دستور iret میشه. ........ به عبارت دیگه این وقفه هیچ تابعی نداره....... علاوه بر این، این وقفه هیچ وقت به صورت مستقیم فراخوانی نمیشه یعنی وقتی که برنامه رو قدم به قدم اجرا میکنید پس از اجرای هر دستور، این وقفه بصورت خود به خود اجرا میشود

اگر بیشتر توضیح بدید حتما شما رو راهنمایی میکنم......


GoOd LuCk

amin joon
دوشنبه 10 بهمن 1384, 00:33 صبح
شما هم کلاسی هستید؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟ ؟؟؟؟؟؟

برای نوشتن این برنامه بصورت مقیم در حافظه باید بصورت زیر عمل کنید:

1- وقفه ی 9h قبلی رو call کنید......این کار باعث میشه که کد اسکن کلید فشرده شده به کد اسکی تبدیل بشه و بعد این دو کد در بافر صفحه کلید قرار داده شوند....

2- تابع 0 از وقفه ی 16h را فراخوانی کنید ....این کار باعث میشه کد اسکی و اسکن که توسط وقفه ی 9h قبلی در بافر صفحه کلید قرار داده شد، از این بافر خوانده شود و در al و ah قرار داده شوند

3- مقدار ax را در cx قرار دهید و تابع 5 از 16h را فراخوانی کنید.......این کار باعث میشه مقادیر کد اسکی و اسکن دوباره در بافر قرار داده شوند(این تابع را به تعداد مورد نیاز فراخوانی کنید)
در این حالت برنامه ی کاربردی کد هایی را که شما در بافر صفحه کلید قرار دادید را میخواند و مثل این است که کاربر چند بار یک کلید را فشار داده

4- این برنامه رو به جای وقفه ی 9h مقیم کنید

بهتر بود سوالتون رو تو یک تاپیک جدید مطرح میکردید


GoOd LuCk

Feremerz
چهارشنبه 15 خرداد 1387, 13:36 عصر
آقا قطعه كد كه caps lock رو روشن خاموش كنه رو ميتوني واسم بنويسي؟