2

I'm writing a real mode OS in NASM, and I'm wondering if there is a way to read keys such as function keys, arrow keys, control, alt, and the like with BIOS interrupts? I appreciate any help you can provide.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847

2 Answers2

3

The keyboard BIOS can help you with this.

Code like

mov ah, 00h
int 16h     ; -> AX

will wait for a keypress and return to you with the ASCII code of the key in AL and the scancode of the key in AH.
For function keys, arrows and the like, you would only look at the scancode because for most of these keys the ASCII code will be zero.

To know about the state of the ALT keys, CTRL keys, or others you can use functions 02h or 12h. Alternatively, you can inspect the BIOS variables in low memory at 0040:0017h and 0040:0018h.


ps I can't currently post comments (browser issue) ...

If the above code produces AX=1E01h it would indeed mean that the user pressed CTRLA.
Care has to be taken with certain ALT key combinations were the code that is returned in AX could depend on whether the keyboard is QWERTY or AZERTY. ALTA, ALTQ, ALTZ, ALTW, ALTM.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • so if after the above code ax = 1E01 then it was ctrl + A? https://stanislavs.org/helppc/scan_codes.html – Jaihson Kresak Feb 27 '22 at 22:40
  • 1
    @JaihsonKresak You might like my utility [OPIN.COM Keys](http://vitsoft.info/opin.htm) which can inspect keyboard port, scancodes, buffer, flags in realtime. – vitsoft Mar 01 '22 at 08:17
2

There are many ways to solve your problem. As Sep Roland stated, you can use BIOS (Basic Input Output System). However, if BIOS is not available, I suggest you use in al, 0x60 to write a basic PS/2 keyboard controller until you can write a proper keyboard driver. For PS/2 keyboard scan-codes (special values that the keyboard returns to let you know what key was pressed), go here: PS/2 keyboard scan codes wikipidea.

A example for the Ctrl key would be:

in al, 0x60            ;get scancode from keyboard and store it in al
cmp al, 0x1D           ;check weather user presses control
je control_pressed     ;if so then go to control_pressed label

However, a important thing to note when using this method is that if you have something like this:

loop:
   in al, 0x60          ;get input from keyboard
   cmp al, 0x1D         ;check if control was pressed
   je control_pressed   ;if so then jump to control_pressed
   jmp loop             ;otherwise go back to loop label

control_pressed:
   mov esi, message     ;| example print call
   call print           ;|
   jmp loop             ;jump back to loop label

it will call the control_pressed label muliple times because the program will loop many times while the user holds down the key even if its a quick tap. To fix this I would do something like this:

control_pressed:
   mov esi, message     ;| example print call
   call print           ;|
.wait:
   in al, 0x60          ;    get keyboard input
   cmp al, 0x9D         ;    check if the user realises the control key
   je loop              ;    if so then jump to loop
   jmp .wait            ;    otherwise go back to .wait label

This makes it so that the function wont loop multiple times for 1 keypress.

realise scan-codes can also be found at PS/2 keyboard scan codes wikipidea

Markian
  • 322
  • 1
  • 12