Works in QEMU but not in Bochs

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
hallooz
Posts: 4
Joined: Sun Jun 22, 2025 10:05 pm

Works in QEMU but not in Bochs

Post by hallooz »

repo: https://github.com/mikhail10101/os-test

I recently tried further implementing a simple page table setup in kernel/arch/i386/mem.c and I have some questions.

In kernel/arch/i386/tty.c, I read that I had to change VGA_MEMORY = 0xB8000 to 0xC00B8000 to keep printing.

I have 2 printf statements in kernel/kernel/kernel.c, one before initMem (defined in mem.c) and one after. The one before initMem would work whether VGA_MEMORY is equal to 0xB8000 or 0xC00B8000. Is this because in kernel/arch/i386/boot.S, I'm mapping both logical addresses to the same physical address? Just to ensure my understanding is correct.

Secondly, my printf statement works in QEMU but not in Bochs and I have no idea why. I've been playing around with it but I can't figure it out.

Any help would be appreciated, thank you!
MichaelPetch
Member
Member
Posts: 832
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Works in QEMU but not in Bochs

Post by MichaelPetch »

Because you identity mapped the first 4MiB of memory and you also mapped 0xb8000 region to the higher half, you can use both addresses. If you were to remove the identity mapping of the first 4MiB after entering the higher half kernel then you wouldn't be able to access via 0xb8000 anymore.

I believe your printf function works but it is not being called in BOCHs. The timings when running in BOCHs and QEMU can be different. After setting up the IDT you do an `STI` instruction that enables interrupts. Each interrupt will call `exception_handler` which does a CLI/HLT which prevents any other code from executing. If a timer interrupt comes in before the first printf then your kernel will just stop in `exception_handler` and never return.

As an experiment in `idt_init` comment out the line that enables interrupts with `STI` and see what happens.

Note: your interrupt and exception stubs don't save and restore registers, and the stubs with an error code don't remove the the error code from the stack before doing the IRET.
hallooz
Posts: 4
Joined: Sun Jun 22, 2025 10:05 pm

Re: Works in QEMU but not in Bochs

Post by hallooz »

MichaelPetch wrote: Sat Jun 28, 2025 7:57 pm Because you identity mapped the first 4MiB of memory and you also mapped 0xb8000 region to the higher half, you can use both addresses. If you were to remove the identity mapping of the first 4MiB after entering the higher half kernel then you wouldn't be able to access via 0xb8000 anymore.

I believe your printf function works but it is not being called in BOCHs. The timings when running in BOCHs and QEMU can be different. After setting up the IDT you do an `STI` instruction that enables interrupts. Each interrupt will call `exception_handler` which does a CLI/HLT which prevents any other code from executing. If a timer interrupt comes in before the first printf then your kernel will just stop in `exception_handler` and never return.

As an experiment in `idt_init` comment out the line that enables interrupts with `STI` and see what happens.

Note: your interrupt and exception stubs don't save and restore registers, and the stubs with an error code don't remove the the error code from the stack before doing the IRET.
I see, that makes more sense! I tried what you said and it worked. I'll also try working on what you noted. Thank you so much!
Post Reply