Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you disable the PC speaker beep interrupt that occurs while looping?

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.

like image 346
bad Avatar asked Sep 06 '17 18:09

bad


1 Answers

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.

like image 103
Ruud Helderman Avatar answered Sep 19 '22 13:09

Ruud Helderman