Aeon Emulator Blog

July 26, 2011

Weird Code Finally Explained

Filed under: Aeon — Greg Divis @ 10:35 pm

Writing something like Aeon meant that I’d often find myself poring over disassembly instructions from some old, clever code. By clever, I mean performance optimizations which seem especially exotic (or just nonsensical) today. Not that we don’t have our own exotic optimizations today, but most of the ones I run into are in old games – and games rarely concern themselves with maintainability: you ship the game, maybe patch it here and there, but ultimately it’s just a piece of consumer software that will likely be discarded in at most a year or two.

Anyway, with that bit of pointless exposition out of the way, I’d like to introduce you to the HLT instruction. It takes no operands, and simply tells the CPU to halt: that is, it will just stop what it’s doing and enter a low-power state until an interrupt wakes it up. It’s employed by operating systems today to conserve energy when the system is idle, but the intended use doesn’t really matter for this article. I was puzzled for a very long time when I came across a HLT instruction in Jazz Jackrabbit some time ago (more specifically, it was in the protected-mode extender that came with Turbo Pascal 7). I figured no DOS game would have any reason to use this instruction intended for operating systems, so I tried in vain to find an emulation bug in Aeon that would explain why a JMP instruction pointed to a HLT.

I finally fired up a debugger on a real DOS system and determined that there was no bug in Aeon. Jazz Jackrabbit was actually trying to halt the CPU. (Never thought I would write that sentence…) Actually, it was trying to halt the CPU from user mode, which according to the Intel documentation on the instruction should cause a General Protection Fault exception. This exception would then be handled in kernel mode, and in the case of Jazz Jackrabbit’s DOS extender, a handler would examine the user mode stack and take some action, then eventually return control to user mode. Basically, they had used a General Protection Fault exception to transfer control to kernel mode.

Why would anything do this? It made no sense to me, but once I implemented this behavior the game loaded up and worked just fine (well, except for the distorted sprites… bah, that’s another story)

Well, recently I’ve finally gotten a copy of Raymond Chen’s book. In it (also on his blog), he relates a story that Windows ended up spending a lot of its time handling Invalid Instruction Exceptions because at the time, causing one of those was the fastest way to switch to kernel mode. Doesn’t seem like much of a stretch that the authors of Turbo Pascal 7’s DOS extender would have used a similar technique…

One mystery solved. Now if only I could figure out those sprites.

Advertisements

Create a free website or blog at WordPress.com.