Page 1 of 1
General Protection Fault after Divide by Zero.
Posted: Thu May 05, 2005 12:02 am
by serverkitty
Hello, Rookie here again!
I just finished re-setting up my exception handler, so I tried testing it by purposely dividing by 0. That works fine, but if I try to do anything else after that, I get a General Protection Fault. What could I be doing wrong, or will I have to post code?
Thanks~ Serverkitty
Re:General Protection Fault after Divide by Zero.
Posted: Thu May 05, 2005 7:48 am
by mystran
There are two possible causes. The first one (the probably one actually) is that there's a problem with your handler, so that it causes a GPF when it returns... or something like that.
Also, IIRC divide by zero is an abort, which means you shouldn't try to resume the code that caused it..
Re:General Protection Fault after Divide by Zero.
Posted: Thu May 05, 2005 8:43 pm
by serverkitty
Ok, I figured it out. It was in my handler.
Code: Select all
%macro ISTUB 1
PUSH GS
PUSH FS
PUSH ES
PUSH DS
PUSHAD
MOV AX, SYS_DATA_SEL
MOV DS, EAX
MOV ES, EAX
MOV FS, EAX
MOV GS, EAX
; Why does it work when I comment these?
;MOV EAX, %1
;PUSH EAX ; Pass the interrupt # to the Kernel Interrupt Handler
CALL _InterruptHandler
;Do I have to pop them after the C function?
POPAD
POP DS
POP ES
POP FS
POP GS
ADD ESP, 8
IRET
%endmacro
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 12:09 am
by AR
; Why does it work when I comment these?
;MOV EAX, %1
;PUSH EAX ; Pass the interrupt # to the Kernel Interrupt Handler
The reason it works without that is because you don't pop it afterwards. And yes that answers the other question, C/C++ functions do not pop their own parameters, in a standard C call the parameters are pushed and popped by the caller.
Also with these interrupt handlers, be aware that the parameters are not
meant to be popped (The compiler usually puts ADD ESP, X to simply delete them) so be aware of that. I had an interesting experience with compiler optimizations where the compiler decided to completely override the parameters since they weren't used in the function which naturally made a big mess when I tried to pop the segment registers [GPF which is incidentally what is happening here, you were popping an invalid value for the segment registers].
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 7:02 pm
by serverkitty
Thank you AR and mystran, that was a great help. Now maybe I can get somewhere with assembler/C.
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 8:38 pm
by serverkitty
OK, I'm still not having much luck here!
I popped that like you said and I'm still getting the GPF. so I tried adding 9 to ESP to delete it and it is still generating a GPF. I'm so lost! :-[
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 9:31 pm
by AR
Code: Select all
%macro ISTUB 1
PUSH GS
PUSH FS
PUSH ES
PUSH DS
PUSHAD
MOV EAX, SYS_DATA_SEL
MOV DS, EAX
MOV ES, EAX
MOV FS, EAX
MOV GS, EAX
PUSH %1 ; Pass the interrupt # to the Kernel Interrupt Handler
CALL _InterruptHandler
ADD ESP, 4 ;Delete PUSH %1 value
POPAD
POP DS
POP ES
POP FS
POP GS
ADD ESP, 8
IRET
%endmacro
How you use this code would be useful, I am a bit confused by the last part ( ADD ESP, 8 ) being in a macro. Are you adding this code as is to the IDT or is there a stub that jumps to it?
In Bochs I recommend inserting "hlt; nop" pairs to let you step through it and print the stack as it goes to see where it messes up.
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 9:58 pm
by serverkitty
I haven't actually tried using Bochs yet, I've been using GRUB to boot up and I really don't feel like waiting for Bochs it to boot from floppy etc... right now I have a test rig with GRUB installed on the hard drive, so all I have to do is insert the floppy and turn the computer on.
This is the code I have so far for the ISR:
It finally does not reboot the computer, but I still get a full screen of GPFs, then after about a minute, the screen turns white! :S
Code: Select all
extern _InterruptHandler
%macro ISTUB 1
PUSH GS
PUSH FS
PUSH ES
PUSH DS
PUSHAD
MOV AX, SYS_DATA_SEL
MOV DS, EAX
MOV ES, EAX
MOV FS, EAX
MOV GS, EAX
PUSH %1 ; Pass the interrupt # to the Kernel Interrupt Handler
CALL _InterruptHandler
ADD ESP, 4 ; Delete PUSH %1 value
POPAD
POP DS
POP ES
POP FS
POP GS
ADD ESP, 8
IRET
%endmacro
isr0: ISTUB 0 ;Divide by 0
isr1: ISTUB 1 ;Debug Exception
isr2: ISTUB 2 ;Non-maskable hardware interrupt
isr3: ISTUB 3 ;Debugger Breakpoint
isr4: ISTUB 4 ;INTO instruction detected overflow
isr5: ISTUB 5 ;BOUND instruction detected overrange
isr6: ISTUB 6 ;Invalid instruction opcode
isr7: ISTUB 7 ;No coprocessor
isr8: ISTUB 8 ;Double fault
isr9: ISTUB 9 ;Coprocessor Segment Overrun
isr10: ISTUB 0x0A ;Invalid task state segment
isr11: ISTUB 0x0B ;Segment not present
isr12: ISTUB 0x0C ;Stack fault
isr13: ISTUB 0x0D ;General protection fault
isr14: ISTUB 0x0E ;Page Fault
isr15: ISTUB 0x0F ;Reserved
isr16: ISTUB 0x10 ;Coprocessor Error
isr17: ISTUB 0x11 ;Alignment Check
isr18: ISTUB 0x12 ;Machine Check
isr19: ISTUB 0x13 ;Reserved
isr20: ISTUB 0x14 ; ''
isr21: ISTUB 0x15 ; ''
isr22: ISTUB 0x16 ; ''
isr23: ISTUB 0x17 ; ''
isr24: ISTUB 0x18 ; ''
isr25: ISTUB 0x19 ; ''
isr26: ISTUB 0x1A ; ''
isr27: ISTUB 0x1B ; ''
isr28: ISTUB 0x1C ; ''
isr29: ISTUB 0x1D ; ''
isr30: ISTUB 0x1E ; Kernel Call
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 10:04 pm
by AR
That's why people don't use real floppies and use floppy disk images instead.
Ok, I see now, you've made a mess of your stack, remove the ADD ESP, 8 and it may work, some exception handlers have error codes (like page fault, GPF, TSS, etc) which do require an ADD ESP, 4 at the end however.
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 10:11 pm
by Chris Giese
Divide error doesn't push an error code on the stack, so you don't need the "ADD ESP, 8"
Anyway, for exceptions that DO push an error code, you want to use "ADD ESP, 4"
The next problem you encounter may be an infinite loop of exceptions. Divide error is a fault, so the IRET returns to the instruction that caused it -- which immediately causes another divide error. (Hmmm, try it and see...could be amusing :)
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 10:54 pm
by serverkitty
Hahahah, that was cool, it doesn't crash but there is an infinite loop of Divide by 0's!
Along with some video buffer corruption. O_o
Thanks guys! Chris, your website is awesome, it has helped me so much.
Now I have to figure out how to stop the divide by 0.
~Serverkitty
Re:General Protection Fault after Divide by Zero.
Posted: Fri May 06, 2005 11:02 pm
by serverkitty
Darn it, just when I thought everything was fixed and good, I opened up the source code, replaced the divide by 0 with an INT 0x1E to test my system call and it still says that it is a divide by 0. This interrupt stuff is really confusing! :S
How does the interrupt handler get a zero from 0x1E?
Re:General Protection Fault after Divide by Zero.
Posted: Sat May 07, 2005 3:20 am
by Pype.Clicker
might you have something broken in your compilation code ?
moreover, as you have previously removed the part that passes the interrupt code to the C code, i'm not surprised that all interrupts appears as a single one
Re:General Protection Fault after Divide by Zero.
Posted: Sat May 07, 2005 10:20 pm
by serverkitty
I'm still having terrible problems with this and I'm beginning to tear my hair out of my scalp! >:(
So I'm deciding just to post the code of the whole thing so you guys can look it over. I must have made a mistake somewhere...
I will be so greatful if someone could take the time to look it over.
Thanks~ Serverkitty
Re:General Protection Fault after Divide by Zero.
Posted: Sun May 08, 2005 11:25 pm
by B.E
try and uncomment your switch statment and place the
Code: Select all
default:
??????setAttribute(0x0C);
??????print("FATAL ERROR: Unknown Exception! System halted.\n");
??????asm("hlt");
??????break;
down the bottom of the switch statment (as that is the normal place you will find this stament)
and with isr.inc uncomment PUSH DWOD %1