I was reworking the way text is streamed to the screen to move towards a simple console that can process events from the keyboard, and ended up with the following system:
- An EventListener class with a virtual function to process some arbitrary event
- An EventListenerKey, inheriting from EventListener, class to specifically handle key press/release events
- A Stream class (just virtual << operator overloads)
- A Window class inheriting from Stream to write text to a portion of the screen. A Display class contains all windows on screen.
- A Console class that inherits from both Window and EventListenerKey
EventListenerKeys are passed to the keyboard driver. It queues up events during interrupt processing, and passes them out to each event listener in the meantime. The Console instance is one of those listeners.
I'm not quite happy with this design, but that isn't the issue right now. The problem is that I can't call any functions of my Console object. QEMU just crashes with "Trying to execute code outside RAM or ROM". I have an instance of Display that contains a Window object, error, and a Console object, console. While the constructor of Display is running, the console object behaves normally. Afterwards, however, the emulator crashes when I try to call member functions. Even with no steps between the constructor returning and calling a member function of the console, I get the same results. I've been staring at my code for hours and I just can't figure out what I'm doing wrong.
What I know so far is that duing the Display constructor call, the display object (and therefore the windows) are allocated on the stack. Afterwards they are somewhere below the stack. That makes sense; the new object is copied off the stack and into System::display. However, is there something about that causing my problem? Since that is pretty much the only thing happening when the console stops working, that's my only guess.
Here's the relevant code:
System::initialize is what creates the Display object
Code: Select all
Display System::display;
void System::initialize()
{
display = Display();
display.printError((uint32_t) &display);
display.printError("\n");
display.initialize();
display.print("hi\n");
panic();
KeyboardTranslator::initialize();
Keyboard::initialize();
InterruptController::init(0x100000);
display.printError("Finished init.\n");
panic();
}
Code: Select all
Display::Display()
{
clear();
console = Console(0, 1, 40, 24);
error = Window(40, 1, 40, 24);
printError((uint32_t) this);
printError("\n");
console << (uint32_t) &console;
}
void Display::initialize()
{
error << (uint32_t) &console;
//Keyboard::addListener(&console);
}