7

While executing a loop in my 8086 assembly programs, there is a keyboard key press threshold where if you press a key too many times the PC speaker will start beeping. It's obnoxious, and it slows down my programs to a crawl since the cpu has to jump away from my program and spend half a second driving the speaker.

I didn't even know this issue existed until I started testing my programs on actual hardware a few months ago. This problem isn't an issue in DosBox, or even in Dos 6.22 installed inside DosBox. So it must be some low level hardware interrupt built into the PC BIOS, I don't know too much about this stuff.

It occurs on my 286 machine, and my Pentium mmx laptop regardless of the operating system.

Even if it's just a dead loop, and i'm not even polling for keyboard input, the beep still happens if I press too many keys

I've tried wrapping just my input code inside cli & sti to hopefully mask my keyboard input from the system, but that doesn't really work. I collect a scancode only at a singular point in my program, so the rest of the time, interrupts are enabled. So the beeping can still occur the vast majority of the time.

There must be some hardware register that I can disable or something. I took a good long look through Boch's ports list (http://bochs.sourceforge.net/techspec/PORTS.LST) looking for something like that, but didn't see anything.

Maybe I could just turn the interrupt off? I imagine that a lot of assembly programmers must've encountered this problem, but Google really isn't helping me at all here.

  • There may be a setting in your BIOS to disable the sound. – Jon Purdy Sep 06 '17 at 18:47
  • Nah, there isn't. Just to be clear, i'm not talking about that little key press beep sound that you can enable in some BIOS as a kind of fake click. This is something that only occurs in the middle of programs. Basically the computer is trying to warn me by shouting at me, "HEY YOU'RE STUCK IN A LOOP! DID YOU KNOW THAT?" It's just an unwanted warning that isn't helpful in my case. – My life is a bug. Sep 06 '17 at 18:53
  • 7
    The BIOS is beeping to warn you about the fact that the [keyboard typeahead buffer](https://support.microsoft.com/en-us/help/43993/how-to-flush-the-keyboard-typeahead-buffer) is full. Apparently your program fails to flush the buffer. Please share some code so that we can tell what method you are using to read keyboard input. – Ruud Helderman Sep 06 '17 at 18:53
  • Honestly all i'm doing is collecting a scancode with `in al, 60h`, then branching based on the scan code. Kind of primitive, I know. Honestly that is all I needed to know. Thank you. At least I have some search terms to Google and I can probably figure it out on my own now. Make that an actual answer, and I'll award you the solution. – My life is a bug. Sep 06 '17 at 18:56
  • 1
    The BIOS installs an interrupt handler for IRQ1 as Interrupt 0x09 in the interrupt table and keeps a keyboard buffer and data in the BDA between 0x0:0x0400 and 0x0:0x500. It is the Int 0x9 interrupt handler that will beep if the buffer is full. If your code isn't doing interrupt driven keyboard input then you can either code a new keyboard handler (int 0x9) that send the master PIC an End of Interrupt(EIO) and then an `iret` or you can tell the Master Programmable Interrupt controller that you don't want keyboard interrupts at all. – Michael Petch Sep 06 '17 at 21:36
  • @Proughgrammor: I wasn’t referring to the “keyboard click” option. As others have said, it’s the keyboard buffer overflowing—since the BIOS is what installs the handler for that, I suspected there may be a setting to disable the beep. – Jon Purdy Sep 06 '17 at 21:39
  • @Proughgrammor Basically I agree with **Ruud Helderman's** answer. To remedy this either use custom interrupt see related QA [Set and reset keyboard Interrupt Service Routines in x86 real mode within DOS with Assembly (NASM)](https://stackoverflow.com/a/45855278/2521214) or here [simple TASM game](https://stackoverflow.com/a/29579522/2521214) using also own interrupt. Another option is to read/clear the key buffer using MS-DOS interrupt time to time see [How to read image file and display on screen in windows tasm dosbox](https://stackoverflow.com/a/45780565/2521214) for example code – Spektre Sep 12 '17 at 08:21

1 Answers1

9

The BIOS is beeping to warn you about the fact that the keyboard typeahead buffer is full. In DOS, this would typically happen with programs which (permanently or temporarily) do not read keyboard input.

In your case, you are reading keyboard input, but not in a proper manner. You are reading directly from hardware (I/O port 60h), but apparently you are not catching the keyboard interrupt (INT 09h). This means that in the background, the BIOS is also processing keyboard input. This has two nasty side effects.

  • The BIOS keyboard typeahead buffer is filling up. Not only does this cause the machine to beep, the unhandled keystrokes also pile up like garbage waiting to spill out once your program exits and falls back to the command prompt.
  • You may miss keystrokes because the BIOS beat you to it.

Basically, there are three ways to resolve this.

  1. Use BIOS calls or DOS calls to read keyboard input.
  2. Make a proper keyboard interrupt handler where you use ports 60h, 61h and 20h to fetch keyboard events ('make' and 'break').
  3. (Not sure about this one anymore:) Directly pull keystrokes from the BIOS keyboard typeahead buffer.

The first option is strongly recommended. The second one is preferred if your application must be able to detect multiple keys being held at the same time (typically video games). This is not a trivial task so you will need some help there.

Ruud Helderman
  • 9,064
  • 1
  • 19
  • 39