Thread: Get Keyboard Character via BIOS Interrupt

  1. #1
    Registered User
    Join Date
    May 2013
    Posts
    8

    Get Keyboard Character via BIOS Interrupt

    Hi,

    I'm writing a little program that is run instead of a bootloader. It's just an excercise to learn more about x86-assembly and the BIOS.
    The following subroutine should wait for a keystroke (if there is none in the buffer) and return its ASCII code.

    Code:
    char getkey(void) {
            short s;
            asm(    "xor %%ah, %%ah\n\t"
                    "int $0x16"
                    : "=al" (s) : );
            return (char)s;
    }
    But it doesn't work as intended, the value returned is always the same. It's probably a really simple problem, but I would appreciate any help.

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    it's possible that there is a keystroke already in the buffer. does it immediately return, or does it still wait? is it possible that the keystroke is more than one byte?
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  3. #3
    Registered User
    Join Date
    May 2013
    Posts
    8
    If there is a keystroke in the buffer, it returns immediately. If there is none, it waits. What do you mean by more than one byte? Each keystroke only registers once.

  4. #4
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    on standard pc hardware, a keycode usually includes the ascii character pressed (if any) and control codes to indicate the presence of shift, ctrl, alt, or other modifier keys. to include all that data, I suspect that it requires more than one byte. try receiving ax into s instead of just al.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  5. #5
    Registered User
    Join Date
    May 2013
    Posts
    8
    Thanks, that allows me to distinguish different keys. But the result is still not what I expected. How do I get an ASCII representation of the keycode?

  6. #6
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    INT 0x16 / AH = 0x00 - get keystroke from keyboard ( blocking, no echo).
    return:
    AH = BIOS scan code.
    AL = ASCII character.
    Kurt

  7. #7
    Registered User
    Join Date
    May 2013
    Posts
    8
    Quote Originally Posted by ZuK View Post
    Kurt
    Yes, I read that when I wrote my program, but shouldn't that mean that my original code is just fine? Because with my original program, I don't get ASCII codes either. It seems that the AL part of AX isn't set as specified (no printable character, indistinguable for different keys). I'm sorry if I'm overlooking something here, but it doesn't make too much sense to me.

  8. #8
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    What operating system are you using? Are you running this program in dos console mode?

    You could test this by creating a tiny program using debug:

    first open up a dos console window
    run debug, and enter these commands, a blank line mean you just press the enter key:

    a100
    xor ah,ah
    int 16
    nop

    g=100,104
    q

    This "program" should pause when you enter the line g=100,104, which tells it to set a break point at 0x104 and to branch to 100, where you entered the first instruction. It should wait for you to enter a key, then break at the nop at insruction 104. You should see the ascii character in AL. To repeat the program, just enter g=100,104 again.

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Zuk, what is the source of that information?
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  10. #10
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by Elkvis View Post
    Zuk, what is the source of that information?
    BIOS and DOS (INT 21H) interrupt call descriptions. There are a lot of these, Here is one example:

    Ralf Brown's Interrupt List - HTML Version

  11. #11
    Registered User
    Join Date
    May 2013
    Posts
    8
    Quote Originally Posted by rcgldr View Post
    What operating system are you using? Are you running this program in dos console mode?

    You could test this by creating a tiny program using debug:

    first open up a dos console window
    run debug, and enter these commands, a blank line mean you just press the enter key:

    a100
    xor ah,ah
    int 16
    nop

    g=100,104
    q

    This "program" should pause when you enter the line g=100,104, which tells it to set a break point at 0x104 and to branch to 100, where you entered the first instruction. It should wait for you to enter a key, then break at the nop at insruction 104. You should see the ascii character in AL. To repeat the program, just enter g=100,104 again.
    Thanks for the advice, but I'm running this on a virtual machine with no operating system installed since I don't have a computer with an actual BIOS. The emulator I'm using is qemu-x86_64.

  12. #12
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by Elkvis View Post
    Zuk, what is the source of that information?
    Sorry can't find it anymore.

  13. #13
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by proggerboy View Post
    Thanks for the advice, but I'm running this on a virtual machine with no operating system installed since I don't have a computer with an actual BIOS. The emulator I'm using is qemu-x86_64.
    So is the compiler producing 16 bit real mode code, which is how an Intel X86 processor boots up?

    I tried using C with asm code and if I use a 32 bit compiler (VC 4.0, or Visual Studio), it gets an exception error on the int 16, probably since it's running with a 32 bit flat model virtual address space, not the 16 bit real mode model used by MSDOS. If I use a 16 bit compiler (like Visual C 2.2 or older), and run it from a dos console window, it works.

    update - obviously this will work if I use Virtual PC with MSDOS installed.
    Last edited by rcgldr; 05-13-2013 at 12:48 PM.

  14. #14
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    what is the numeric value of al and ah after the interrupt returns?
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  15. #15
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by Elkvis View Post
    what is the numeric value of al and ah after the interrupt returns?
    al is the ascii value (if one exists), and ah is the "scan code". You can do a web search for keyboard scan code. These changed during the PC to AT transition. I don't recall if they changed again. I found some size, but the codes were difficult (small) to read.
    Last edited by rcgldr; 05-13-2013 at 12:49 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading a character from the keyboard getchar()
    By mnml in forum C Programming
    Replies: 6
    Last Post: 10-21-2011, 09:05 AM
  2. Fake a Keyboard Interrupt.
    By nicka in forum Networking/Device Communication
    Replies: 0
    Last Post: 09-04-2009, 03:19 AM
  3. How do I input an unbuffered character via the keyboard???
    By Michael_in_Ohio in forum C Programming
    Replies: 1
    Last Post: 03-23-2008, 12:00 PM
  4. bios and disabled keyboard
    By xddxogm3 in forum Tech Board
    Replies: 4
    Last Post: 12-18-2006, 12:01 PM
  5. BIOS Interrupt Reference
    By bludstayne in forum Tech Board
    Replies: 1
    Last Post: 03-21-2004, 12:40 PM