Page 1 of 1

Stack Segment Exception

Posted: Mon Feb 17, 2025 10:16 am
by sboydlns
I am working a 32-bit OS using GNU assembler and gcc. I am testing it using QEMU. I have written my own boot loader. The boot loader loads my kernel at 0x7e00. I know this is not necessarily recommended but until I get an ATA driver working this was simplest. I have set up a region of low memory starting at 0x500 to hold various system tables that my OS needs.

My GDTR (0x508) looks like this:

Code: Select all

0508: 9F0010050000
My GDT (0x510) looks like this:

Code: Select all

0510: 00000000 00000000 FFFF0000 009ACF00
0520: FFFF0000 0093CF00 00000000 00000000
I use the value 0x08 for %CS and 0x10 for all other segment registers, including %SS. I set %ESP to 0x07FFF0 to get it well away from kernel code and data.

Everything was going well until I enabled interrupts (STI). As soon as I enable interrupts I start getting Stack Segment Fault exceptions when I try to call a C subroutine.

Before enabling interrupts %CS = 0x10 and %ESP = 0x07FFD0.

After enabling interrupts and calling a C function I get a Stack Segment Fault. In the exception handler %SS = 0x10 and %ESP = 0x07FF84.

To my way of thinking all of these values fall well within the limits of my data segment. I can't figure out why I am getting a Stack Segment Fault.

Any help is appreciated.

Re: Stack Segment Exception

Posted: Mon Feb 17, 2025 10:39 am
by iansjack
What’s the error code?

Re: Stack Segment Exception

Posted: Mon Feb 17, 2025 10:59 am
by MichaelPetch
I'd recommend running QEMU with the option `-M smm=off -d int -no-shutdown -no-reboot` and show us the last few exceptions that occurred. Can you provide about the last 50 lines of output from that?

Re: Stack Segment Exception

Posted: Mon Feb 17, 2025 2:19 pm
by sboydlns
Thanks for your replies. I finally found the problem. I made a dumb @$$ mistake in the PIC initialisation code that caused the interrupts to not be remapped. Hence interrupts from the PIC were firing on X86 reserved interrupts.

Instead of this:

movb $ICW1_INIT | ICW1_ICW4, %al # start initialisation in cascade mode

I had this:

movb $ICW1_INIT || ICW1_ICW4, %al # start initialisation in cascade mode

That second line looked right for the longest time. Trouble is that always evaluated to 0x01 instead of 0x11.

Anyway, everything is happy again for a little while. I'm getting keyboard input now, so on to the next step.