13 January 2004 (Revised 16 January 2004) Waiting for a keypress This will be a quick-and-dirty entry on running code when the user presses a key. Code The full code is here. The code here checks an I/O port for a keypress, so it works in both real mode and protected mode. If I called a BIOS service to get a keypress, the code would work only in real mode. The code also polls for a keypress. This is not the "proper" way to get a keypress because it means that the CPU is spending almost all of its time waiting for the keypress and not doing other things. The "proper" way is to set up an interrupt routine. However, what I have here is code that handles only one task — dumping another sixteen bytes of memory to the screen when the user presses a key — so polling is fine for now. The first thing the code here does is to set up the FS and BX registers for the call to dump_16. I'll be dumping the contents of segment zero, so I set FS:BX to 0000:0000. xor bx, bx mov fs, bx The code then polls for a keystroke. It continually tests bit zero of port 0x64 until it comes up set (equal to one), which means that there is data in the keyboard buffer. .1: in al, 0x64 test al, 1 jz .1 There is data in the keyboard buffer both when a key is pressed and when a key is released. I want to dump memory only when a key is pressed, so I grab the scancode so I can verify that the key event was in fact a keypress. in al, 0x60 If the high bit (bit 7) of the scancode is set, then the key is being released, so I'll want to go back and poll for another keystroke. (Actually scancodes are a little more complicated than that, but this explanation is close enough for my purposes here.) test al, 0x80 jnz .1 If the key is being pressed, dump sixteen bytes of memory to the screen — then go back and poll for another keystroke. call dump_16 jmp .1 Results You won't see anything happen until you press a key. Sixteen bytes are dumped to the screen when you press a key (but not also when you release the key), so the keyboard-test code works. Unfortunately I also noticed that the screen-scrolling routine doesn't work correctly. When the screen fills up and it's time to scroll the screen up, the screen is erased and you see only one line on the screen. Oh well, I'll fix this later. [UPDATE 2004-01-16: It was while running this code that I noticed two bugs. [The first, I'm embarrassed to admit, is in scroll_up (from "Hex dump, part 1"). I should have tested this more carefully back when I wrote it. Oh well. The fix is in the next entry. [The second bug is that, after a while, the computer starts beeping whenever you hit a key. I figured out why: I'm polling the keyboard input port, but so is the BIOS. While my code is busy reacting to keypresses, the BIOS is storing those keypresses in a buffer, and my code isn't removing them from the buffer. So after a few keypresses (usually fifteen), the buffer fills up, and then, whenever you hit a key, the BIOS tries to put the keypress data into the buffer and emits a beep because the buffer is full. But that's OK for now — the purpose of this entry was to produce code that did something when you pressed a key, and the code still dumps another sixteen bytes whenever you press the key, even when the buffer is full.] Check the index for other entries. |