Normally, newer DOS applications are actually easier to run on the board because they are compiled with standardized libraries that tend to do more things by the book instead of clever I/O trickery. But Microsoft QBASIC was different. It worked perfectly until I opened any of its menus, upon which it hung immediately.
Debugging 8086 code that was compiled from a high level language is no fun, especially since QBASIC installs its own INT 16h handler which makes it impossible to debug it from a console. But after a week of poking around, I concluded that after opening the menu it is getting stuck in a quite tight loop which does basically nothing except check some internal variables, whose values never change.
Obviously, something must change these variables outside that loop. An obvious candidate is an interrupt handler. But the timer interrupt is already working well, so which interrupt could it be? As it turned out, QBASIC also hooks up the INT 09h vector, which corresponds to IRQ1. And IRQ1 is the keyboard interrupt.
So, the apparent sequence of events is like this:
- After a keypress is detected and processed (which means, for example, opening the “File” menu when Alt+F is pressed), an internal flag is zeroed.
- When IRQ1 handler is executed, it sets the flag again.
- An internal loop in the code checks this flag constantly, and only calls INT 16h to look for a keypress if this flag is set.
In other words, QBASIC will only check the keyboard when an IRQ1 occurs first. On a PC, this is what normally happens – all incoming keypresses are processed in the IRQ1 handler which then puts them into the keyboard buffer from which they are read by INT 16h calls. But on the CBM-II the 8088 has no keyboard interrupt as the keyboard buffer is handled on the 6509 processor side.
To simulate IRQ1, the 60 Hz timer interrupt is used (which, incidentally, is also the same one that the 6509 uses for scanning the keyboard). If this interrupt handler finds out that a key is waiting in the keyboard buffer on the 6509 side, it executes an
INT 09h instruction to simulate IRQ1. The QBASIC handler for this interrupt unblocks the “key pressed” flag, which causes the main loop to call INT 16h to process the key press.