Getting Keyboard Input

How do I let the user interact with my program through the keyboard?????

If you're finally over the hype of running your own program at boot time, intimately talking to the CPU, or if you were never even in it for the "coolness factor" in the first place, then you probably want to do something more interesting.

Getting keyboard input is pretty simple. You just set ah to 0 and then you call the interrupt 0x16:

0\e4\cdSYN

Walkthrough

The interrupt 0x16 is called the BIOS Keyboard Service interrupt. It provides a small suite of functions related to the keyboard that we can use.

The function we're interested in is the "Get Keystroke" function, which is a blocking function that waits until the user presses a key on the keyboard. Once the user presses a key, the interrupt stores (1) the ASCII byte representing the character in al and the key's scancode in ah. Once it's done that, the interrupt finishes and the CPU comes back to executing our code.

Print Loop

First thing I'll do is set up a "print loop" program to just print out whatever character I type with my keyboard, repeatedly. The rationale behind this is that it's basically the simplest, semi-interesting thing I could do to make sure that the keyboard interrupt and "get keystroke" function are supported by my BIOS:

0\e4 ; XOR ah, ah		XORing a value with itself results in 0.
\cdSyn ; INT 0x16		The keyboard service interrupt.
; Once the INTerrupt returns, AL will store the character that I typed on the keyboard, so we can just use the print interrupt:
\b4Sho ; MOV ah, 0x0e		This selects the "print character" function
\cdDle ; INT 0x10
\eb\f6 ; JMP $-10		This jumps backwards by 10 bytes, which will put the CPU back at the start of this program.
; After it runs this, the CPU will execute the XOR ah,ah again.

I used XOR to clear out ah. You could also use a MOV or another instruction that makes ah become 0.

People say XOR is faster than doing a MOV, because of the way CPUs work. Apparently, a MOV ah, 0 would require "fetching and decoding the immediate byte 0". I haven't tested how many cycles the XOR takes, myself (yet).

That turned out pretty nice:

The BIOS interprets ASCII characters a lot like ye olden typewriters do: Pressing Enter would print a carriage return, which would move the cursor left, to the front of the line it was on, but not move the cursor down, at all. Typing a backspace would move the cursor one character to the left, but would not erase the character at that position. If you started typing afterwards, that character would just be overwritten. Also, Ctrl codes work similarly to how Linux terminal applications interpret them. For example, pressing Ctrl + J would type a line feed character, which would move the cursor down one line (but not to the front of the line).

My BIOS is happy interpreting the three characters, Line Feed (Lnf), Carriage Return (Crg), and Backspace (Bsp) as functional characters, meaning when I type these, they behave as I described.

Another thing that's interesting is that my BIOS has glyphs for a lot of the characters that don't have a visual representation, e.g. the ASCII control codes, and for many bytes outside of ASCII (greater than 127). These seem to match Windows's alt codes pretty well.

In fact, you can use alt codes, similar to Windows, on (my) BIOS by holding ALT and then typing a numeric sequence on the numpad. The sequence is reduced mod 256—meaning if you enter a number past 256, it loops back around, e.g. entering 258 is like entering 2 because it's 2 above 256—and then a glyph corresponding to that value is typed.

Prompting the User

Since that works, let's make an interactive prompt. We'll ask the user to choose an option from a menu and then do something depending on what number they press. First we'll want to write out the menu. Then we'll wait until they press a key and, if it's one of the menu options, handle it appropriately.

\ebrSelect an option:
1. Print every available character.
2. Print Loop

###