flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
Ralph 01 Mar 2004, 07:32
My OS is based on forth, but I'm sure you can figure out how to make it work. This is the source to ACCEPT:
Code: ;accept.wrd ;Reads character string from keyboard. limited. accept: dpop edi mov dword [.buffer_start],edi sub ecx,ecx mov ebp,ASCIITableL .a: call .get_key .b: cmp al,KBksp jz .backspace dec ecx cmp al,KEnter jz .done cmp ecx,TIBSIZE jg .a stosb pusha dpush eax call emit popa inc ecx jmp .a .done: dpush ecx ret .backspace: push .b dec ecx cmp edi,dword [.buffer_start] jle .get_key push edi sub edi,edi sub dword [_cursor],02h mov edi,dword [_cursor] add edi,VGASEGMENT mov eax,dword [_color] mov al,20h stosw pop edi dec edi dec ecx jmp .get_key .buffer_start dd 0 .get_key: sub eax,eax @@: in al,64h and al,01h jz @b ;wait for key in al,60h sub edx,edx test al,80h jz @f inc edx @@: and al,7Fh cmp al,39h ja .get_key ;filter ignored keys mov ebx,ebp xlatb or al,al js .shift jz .get_key or dl,dl jnz .get_key inc ecx ret .shift: or dl,dl jnz @f mov ebp,ASCIITableU jmp .get_key @@: mov ebp,ASCIITableL jmp .get_key ASCIITableL: DB 00, KEsc, "1234567890-=", KBksp, KTab DB "qwertyuiop[]", KEnter, KCtrl, "asdfghjkl;'`", KLShift, "\zxcvbnm,./" DB KRShift, KPrtScr, KAlt, KSpace, KCaps ASCIITableU: DB 00, KEsc, "!@#$%^&*()_+", KBksp, KTab DB "QWERTYUIOP{}", KEnter, KCtrl, 'ASDFGHJKL:"~', KLShift, "|ZXCVBNM<>?" DB KRShift, KPrtScr, KAlt, KSpace, KCaps KEsc = 27h KBksp = 08h KTab = 09h KEnter = 0Ah KCtrl = 00h KLShift = -1h KRShift = -1h KPrtScr = "*" KAlt = 00h KSpace = 20h KCaps = -2h Hope that helps. Last edited by Ralph on 12 Jun 2004, 23:11; edited 1 time in total |
|||
![]() |
|
Tomasz Grysztar 01 Mar 2004, 10:15
You can use the keyboard handler from my dead Titan OS project, it allows to use custom conversion tables. Below is the KEYBOARD.INC file from that system, the "irq_1" is the handler for keyboard IRQ (if you don't reprogramm the PIC, it is interrupt 9), "int_22h" is the handler for interrupt 22h, which in Titan was to access keyboard functions (like BIOS interrupt 16h).
Code: KEYS_MAX = 10h ; size of keyboard buffer irq_1: push eax ecx ds push FLAT_SEL pop ds in al,60h ; read scan code cmp al,0F0h ja irq_1_exit ; ignore if special scan code movzx ecx,[keys_counter] lea ecx,[keys_data + 4*ecx] cmp [keys_counter],KEYS_MAX ; check for full buffer je keys_data_full mov ah,[ecx] cmp ax,0E02Ah je ignore_special_code cmp ax,0E0AAh je ignore_special_code mov [ecx],ax ; store key info cmp al,0E0h ; if prefix only, exit interrupt je irq_1_exit cmp al,0E1h je irq_1_exit cmp al,0F0h je irq_1_exit push [keyb_status] pop word [ecx+2] ; store keyboard status inc [keys_counter] ; key information is full jmp keyb_status_check ignore_special_code: mov byte [ecx],0 jmp irq_1_exit keys_data_full: mov ah,[ecx] mov [ecx],al cmp ah,0E0h je keyb_status_check xor ah,ah keyb_status_check: ; check for change of keyboard status lea ecx,[keyb_status_table] check_key: cmp byte [ecx],0 ; end of table? je irq_1_exit ; if yes, exit interrupt cmp ax,[ecx] ; compare key codes je keyb_status_change ; if equal, change keyboard status add ecx,3 jmp check_key keyb_status_change: mov ax,1 mov cl,[ecx+2] ; CL = number of bit and command test cl,10h jnz set_bit test cl,20h jnz switch_bit clear_bit: ; clear bit in keyboard status word shl ax,cl not ax and [keyb_status],ax jmp irq_1_exit set_bit: ; set bit in keyboard status word and cl,0Fh shl ax,cl or [keyb_status],ax jmp irq_1_exit switch_bit: ; switch bit in keyboard status word and cl,0Fh shl ax,cl xor [keyb_status],ax call set_keyb_leds irq_1_exit: in al,61h ; give finishing information out 61h,al ; to keyboard... mov al,20h out 20h,al ; ...and interrupt controller pop ds ecx eax iret ; exit interrupt set_keyb_leds: mov al,0EDh ; keyboard command 0EDh: out 60h,al ; set/reset mode indicators keyb_wait: in al,64h test al,10b ; is input buffer full? jne keyb_wait ; if yes, wait mov al,byte [keyb_status] and al,111b out 60h,al ; set keyboard LEDs ret int_22h: push ds es cli cld push FLAT_SEL pop ds push ds pop es or ah,ah ; function 00h: jz check_for_key ; check for key cmp ah,01h ; function 01h: je read_key ; read key cmp ah,10h ; function 10h: je get_keyb_status ; get keyboard status cmp ah,11h ; function 11h: je set_keyb_status ; set keyboard status cmp ah,20h ; function 20h: je get_conversion_table ; get key conversion table cmp ah,21h ; function 21h: je set_conversion_table ; set key conversion table pop es ds mov eax,_function_unavailable or byte [esp+8],1 ; set CF iret check_for_key: cmp [keys_counter],0 je no_key pop es ds and byte [esp+8],not (1 shl 6); clear ZF and byte [esp+8],not 1 ; clear CF iret no_key: pop es ds or byte [esp+8],1 shl 6 ; set ZF and byte [esp+8],not 1 ; clear CF iret get_keyb_status: mov bx,[keyb_status] pop es ds and byte [esp+8],not 1 ; clear CF iret set_keyb_status: mov [keyb_status],bx call set_keyb_leds pop es ds and byte [esp+8],not 1 ; clear CF iret get_conversion_table: mov ebx,[key_conversion_table] pop es ds and byte [esp+8],not 1 ; clear CF iret set_conversion_table: mov [key_conversion_table],ebx pop es ds and byte [esp+8],not 1 ; clear CF iret read_key: push ecx esi edi sti ; enable interrupts wait_for_key: movzx ecx,[keys_counter] or cl,cl ; is any key in buffer? jz wait_for_key ; if no, wait cli lea ecx,[keys_data] xor al,al xchg ax,[ecx] ; get and clear scan code info mov bx,[ecx+2] ; get keyboard status lea esi,[ecx+4] lea edi,[ecx] movzx ecx,[keys_counter] rep movsd ; move keys data dec [keys_counter] ; key removed from buffer xor dl,dl mov esi,[key_conversion_table] key_conversion: mov cx,[esi] or cl,cl ; end of table? je key_converted ; yes, ASCII code is 0 add esi,2 compare_status: mov di,bx and di,[esi] ; compare only bits from mask cmp di,[esi+2] ; compare keyboard status je scan_table ; if equal, search for key code add esi,4 dec cl jnz compare_status ; compare next status movzx edi,ch imul edi,3 add esi,edi jmp key_conversion ; next part of table scan_table: movzx edi,cl lea esi,[esi+4*edi] compare_key: cmp ax,[esi] ; compare key codes je convert_key ; if equal, get ASCII code add esi,3 dec ch jnz compare_key ; compare with next key code jmp key_conversion ; next part of table convert_key: mov dl,[esi+2] ; DL = ASCII code for this key key_converted: ; AL = scan code, AH = prefix pop edi esi ecx ; BX = keyboard status pop es ds and byte [esp+8],not 1 ; clear CF iret keyb_status dw 0 ; current keyboard status keys_counter db 0 ; number of keys in buffer keys_data rd 2*KEYS_MAX ; keyboard buffer db 0 keyb_status_table: db 2Ah,0, 13h ; LShift press - set bit 3 db 80h+2Ah,0, 03h ; LShift release - clear bit 3 db 36h,0, 14h ; RShift press - set bit 4 db 80h+36h,0, 04h ; RShift release - clear bit 4 db 1Dh,0, 15h ; LCtrl press - set bit 5 db 80h+1Dh,0, 05h ; LCtrl release - clear bit 5 db 1Dh,0E0h, 16h ; RCtrl press - set bit 6 db 80h+1Dh,0E0h, 06h ; RCtrl release - clear bit 6 db 38h,0, 17h ; LAlt press - set bit 7 db 80h+38h,0, 07h ; LAlt release - clear bit 7 db 38h,0E0h, 18h ; RAlt press - set bit 8 db 80h+38h,0E0h, 08h ; RAlt release - clear bit 8 db 46h,0, 20h ; ScrollLock press - switch bit 0 db 45h,0, 21h ; NumLock press - switch bit 1 db 3Ah,0, 22h ; CapsLock press - switch bit 2 db 0 key_conversion_table dd default_table default_table: db 3 ; number of keyboard status cases db 26 ; number of key codes dw 111111100b ; keyboard status mask dw 000000000b ; keyboard status dw 111101100b dw 000001100b dw 111110100b dw 000010100b db 10h,0, 'q' ; scan code and matching ASCII code db 11h,0, 'w' db 12h,0, 'e' db 13h,0, 'r' db 14h,0, 't' db 15h,0, 'y' db 16h,0, 'u' db 17h,0, 'i' db 18h,0, 'o' db 19h,0, 'p' db 1Eh,0, 'a' db 1Fh,0, 's' db 20h,0, 'd' db 21h,0, 'f' db 22h,0, 'g' db 23h,0, 'h' db 24h,0, 'j' db 25h,0, 'k' db 26h,0, 'l' db 2Ch,0, 'z' db 2Dh,0, 'x' db 2Eh,0, 'c' db 2Fh,0, 'v' db 30h,0, 'b' db 31h,0, 'n' db 32h,0, 'm' db 3 db 26 dw 111101100b dw 000001000b dw 111110100b dw 000010000b dw 111111100b dw 000000100b db 10h,0, 'Q' db 11h,0, 'W' db 12h,0, 'E' db 13h,0, 'R' db 14h,0, 'T' db 15h,0, 'Y' db 16h,0, 'U' db 17h,0, 'I' db 18h,0, 'O' db 19h,0, 'P' db 1Eh,0, 'A' db 1Fh,0, 'S' db 20h,0, 'D' db 21h,0, 'F' db 22h,0, 'G' db 23h,0, 'H' db 24h,0, 'J' db 25h,0, 'K' db 26h,0, 'L' db 2Ch,0, 'Z' db 2Dh,0, 'X' db 2Eh,0, 'C' db 2Fh,0, 'V' db 30h,0, 'B' db 31h,0, 'N' db 32h,0, 'M' db 1 db 5 dw 111100000b dw 000000000b db 39h,0, ' ' db 35h,0E0h, '/' db 37h,0, '*' db 4Ah,0, '-' db 4Eh,0, '+' db 1 db 21 dw 111111000b dw 000000000b db 02h,0, '1' db 03h,0, '2' db 04h,0, '3' db 05h,0, '4' db 06h,0, '5' db 07h,0, '6' db 08h,0, '7' db 09h,0, '8' db 0Ah,0, '9' db 0Bh,0, '0' db 0Ch,0, '-' db 0Dh,0, '=' db 1Ah,0, '[' db 1Bh,0, ']' db 27h,0, 3Bh db 28h,0, 27h db 29h,0, 60h db 2Bh,0, '\' db 33h,0, ',' db 34h,0, '.' db 35h,0, '/' db 2 db 21 dw 111110000b dw 000010000b dw 111101000b dw 000001000b db 02h,0, '!' db 03h,0, '@' db 04h,0, '#' db 05h,0, '$' db 06h,0, '%' db 07h,0, '^' db 08h,0, '&' db 09h,0, '*' db 0Ah,0, '(' db 0Bh,0, ')' db 0Ch,0, '_' db 0Dh,0, '+' db 1Ah,0, '{' db 1Bh,0, '}' db 27h,0, ':' db 28h,0, 22h db 29h,0, 7Eh db 2Bh,0, '|' db 33h,0, '<' db 34h,0, '>' db 35h,0, '?' db 1 db 11 dw 111111010b dw 000000010b db 47h,0, '7' db 48h,0, '8' db 49h,0, '9' db 4Bh,0, '4' db 4Ch,0, '5' db 4Dh,0, '6' db 4Fh,0, '1' db 50h,0, '2' db 51h,0, '3' db 52h,0, '0' db 53h,0, '.' db 2 db 1 dw 110111000b dw 000100000b dw 111011000b dw 001000000b db 39h,0, 0FFh db 0 Because I'm not going to continue that old project (I've lost sources of more advanced versions), I'm releasing the Titan source as Public Domain code, which means you can do with it anything you want. |
|||
![]() |
|
StringCheesian 01 Mar 2004, 19:32
Thanks Privalov and Ralph!
|
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.