Two problems

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
Crumble14
Posts: 16
Joined: Tue Jan 01, 2019 4:10 pm
Location: Normandy, France

Two problems

Post by Crumble14 »

Hello,

I'm currently facing 2 problems:

- When calling global constructors.
Calling the _init function makes QEMU go back to the GRUB selection screen.

- When writing to 0xB8000
When I try to write text on the screen using the VGA text mode buffer, it seems like it doesn't work (I tried debugging with GDB. Before and after calling my function vga_clear, the value of the whole buffer is 0xFF for each byte instead of 0x00)

Here is my code: https://gitlab.com/Crumble14/crumbleos/ ... b5e37912d1
Student at School 42 Paris (FR: https://42.fr/)
mihe
Member
Member
Posts: 38
Joined: Sun Oct 21, 2018 1:37 pm

Re: Two problems

Post by mihe »

I would suggest trying BOCHS to debug while writing on VGA memory. What I usually do is:

I inline one magic breakpoint before the piece of code I want to debug in the c Kernel:

Code: Select all

	asm(
		"xchg bx, bx;");
I make sure you include "magic_break: enabled=1" in your .bxrc file

I execute BOCHS and F5 to execute until the magic breakpoint.

From this point, I use CTRL + F7 (Physical dump) to show 0xB8000 (VGA map) and F2 for the Stack content, while I F11 for step-by-step debugging.

On the other side, I compile my kernel using -g parameter, to include debug information and I have the output of an objdump "-D -M Intel --source" on one side of the screen.

This way I have full information to follow what exactly the kernel is doing and it helps me figure out quickly what is wrong.

This is an example:
PS: Ignore the code and the comments on my screenshots, it is just garbage. It is just to show how I debug :-)

ORIGINAL CODE:

Image

OBJDUMP OF MACHINE CODE WITH INTERLEAVED C CODE:

Image

BOCHS STOPPED AT BREAKPOINT WITH VGA CONTENT:

Image

Hope it helps !
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Two problems

Post by bzt »

Crumble14 wrote:Calling the _init function makes QEMU go back to the GRUB selection screen.
This sounds like a triple-fault. That means, you have a fault, but the exception handler cannot be accessed either, therefore a new fault raised, which in turn cannot be handled either. The default behaviour of x86 is to reset the CPU when 3 faults accour in a row (hence you end up in GRUB again). Try to run qemu with "-d int" to see what exception or fault occurs first.
Crumble14 wrote:I tried debugging with GDB. Before and after calling my function vga_clear, the value of the whole buffer is 0xFF for each byte instead of 0x00)
That's definitely not the video RAM buffer. Reading 0xFF suggests you are reading from the wrong memory offset. You should read altering bytes, just like on mihe's screenshot, because text mode contains ASCII codes and attributes one after another. On the screenshot you can see 0x20 and 0x07 which means space character with white on black background. 0xFF as an attribute would mean blinking bright white on white, very very unlikely.

Cheers,
bzt
Crumble14
Posts: 16
Joined: Tue Jan 01, 2019 4:10 pm
Location: Normandy, France

Re: Two problems

Post by Crumble14 »

bzt wrote:This sounds like a triple-fault. That means, you have a fault, but the exception handler cannot be accessed either, therefore a new fault raised, which in turn cannot be handled either. The default behaviour of x86 is to reset the CPU when 3 faults accour in a row (hence you end up in GRUB again). Try to run qemu with "-d int" to see what exception or fault occurs first.
I tried running qemu with "-d int". It printed many things out, including:

Code: Select all

check_exception old: 0xffffffff new 0xd
     0: v=0d e=6288 i=0 cpl=0 IP=0010:00100110 pc=00100110 SP=0018:00107048 env->regs[R_EAX]=36d76289
and

Code: Select all

check_exception old: 0xd new 0xd
     1: v=08 e=0000 i=0 cpl=0 IP=0010:00100110 pc=00100110 SP=0018:00107048 env->regs[R_EAX]=36d76289
So I guess you are right. However I don't know how to read this x)
Student at School 42 Paris (FR: https://42.fr/)
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Two problems

Post by bzt »

Hi,

It seems you got an exception 0xd. Open up the intel manual and check which exception belongs to number 13. The next thing is, figure out which code was loaded at IP (0x100110), and find that in your source. There're several ways, one would be to disassemble instrutions (a few before and after the faulting address) and look for those mnemonics in your source. The point is, figure out which source line corresponds to address 0x100110. Once you know the instruction that's causing the fault, look it up in the intel manual, and read on which conditions it throws a general protection fault. That will give you a clue what your code is missing. Now that you know where the misbehaving instruction is located in you source, and why it's misbehaving, you can start to fix it.

If your code runs perfectly in bochs, then you can also compare the environment, look for register values that are different. This might give you the idea what you haven't set up properly (and initialized differently by bochs and qemu).

Cheers,
bzt
MichaelPetch
Member
Member
Posts: 799
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Two problems

Post by MichaelPetch »

Remove the multiboot2 address_tag and see if your call to _init works. As for displaying characters.If you have requested a framebuffer GRUB is probably going to toss you into a graphics mode. You won't be able to write to 0xb8000 text video memory and have that updated on the display. In graphics mode you will have to render the characters yourself.
Crumble14
Posts: 16
Joined: Tue Jan 01, 2019 4:10 pm
Location: Normandy, France

Re: Two problems

Post by Crumble14 »

MichaelPetch wrote:Remove the multiboot2 address_tag and see if your call to _init works. As for displaying characters.If you have requested a framebuffer GRUB is probably going to toss you into a graphics mode. You won't be able to write to 0xb8000 text video memory and have that updated on the display. In graphics mode you will have to render the characters yourself.
Okay, you just solved both my problems at once. Thanks everyone for helping me! :)

Just one last question: Why does removing the address_tag make the call to _init work ?
Student at School 42 Paris (FR: https://42.fr/)
Post Reply