Page 1 of 2
Division Error to Reboot
Posted: Sun Jun 04, 2006 11:38 pm
by Tolga
Again me. ;D Hi. I wrote interrupts. For test, i wrote this code;
int i = 0;
i = 5 / i;
But when this code executed, computer rebooting. What is the matter? Why don't my code run? :-\
Re:Division Error to Reboot
Posted: Mon Jun 05, 2006 12:55 am
by blip
The CPU is most probably triple-faulting for any number of reasons. The IDTR could be pointing to garbage instead of your IDT, the IDT entry for your handler could be somehow wrong, or your handler itself does something to trigger it. There are so many possibilities that it's impossible to say without seeing any code.
Re:Division Error to Reboot
Posted: Sat Jun 10, 2006 2:13 am
by crackers
Try to execute int 0 and see what happens.
Re:Division Error to Reboot
Posted: Sat Jun 10, 2006 7:40 am
by Ryu
Am I missing something or...
Dividing by zero will generate a #DE exception. In the C code "5" is your dividend, and "i" is your divisor.
Re:Division Error to Reboot
Posted: Sun Jun 11, 2006 2:57 pm
by Tolga
My problem changed. Now "int 0" running. But
line = 0;
line = 5 / line;
command already rebooting computer. "int 0" runs after c code.
sti
call _main
int 0
cli
hlt
Re:Division Error to Reboot
Posted: Sun Jun 11, 2006 3:14 pm
by Ryu
Your not making any sense. The C code and software "int 0" to do what exactly? Test if the exception handler is working properly? (What you explained seems like the C Code is in main() in which case theres no need to do "int 0" to further test)
Some things you need to provide us:
1) Provide us with some debugging information, such as register dumps from Bochs. This will allow us to see if your handling this in real mode or protected mode and some other details.
2) Show the code you use to install the exception handler. So we can make sure your correctly setting the IDT or IVT correctly.
Re:Division Error to Reboot
Posted: Sun Jun 11, 2006 4:36 pm
by Cjmovie
More specifically, it would be a lot easier to figure out what's wrong if you showed us your IDT loading code/structures and your full 'main' function.
Re:Division Error to Reboot
Posted: Sun Jun 11, 2006 4:37 pm
by Tolga
If I use "line = 5 / line" command, bochs rebotting and it is showing that
"exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting"
But if i don't use, everythink is ok.
Re:Division Error to Reboot
Posted: Sun Jun 11, 2006 4:43 pm
by Cjmovie
Yes, but we need to see the entire main function, and where you load the IDT.
Re:Division Error to Reboot
Posted: Sun Jun 11, 2006 6:38 pm
by Ytinasni
Tolga: What are you expecting to happen?
Doing a division by zero will cause a DivByZero fault, which invokes interrupt #0.
If that fails, the double fault handler (interrupt #8)
If THAT fails, (a "Triple fault"), the computer resets.
If you knew this, please be more precise about what's wrong, and what help you want.
If you didnt, there is a thread titled ".:QuickLinkz:. <-- read this before you post !".
PLEASE READ IT.
In particular, the "How to ask questions page" is useful, and the llinks to other resources, including the
FAQ.
Re:Division Error to Reboot
Posted: Sun Jun 11, 2006 11:23 pm
by Tolga
At the end of, i solved my problem.
Working Code
///////////////////////////////////////
int main(void)
{
tidt idt;
idt.set_idt_item( 0, 0x08, (unsigned)isr0, 0x8E );
}
///////////////////////////////////////
I don't understand this isn't working.
///////////////////////////////////////
void set_item( class tidt idt_class_name )
{
idt_class_name.set_idt_item( 0, 0x08, (unsigned)isr0, 0x8E );
}
int main(void)
{
tidt idt;
set_item( idt );
}
Re:Division Error to Reboot
Posted: Mon Jun 12, 2006 4:20 am
by crackers
My guess is that you messed up something with SS descriptor. Lately I've similar problems because my SS and DS segments had diffrent base addresses. Normally I would try to declare idt as global variable and check if it works
Code: Select all
tidt idt;
void set_item( class tidt idt_class_name )
{
idt_class_name.set_idt_item( 0, 0x08, (unsigned)isr0, 0x8E );
}
int main(void)
{
set_item( idt );
}
but since you're using objects you'll have turn off startup code in gcc and call constructor of tidt manualy to see if this works.
Re:Division Error to Reboot
Posted: Mon Jun 12, 2006 11:32 am
by Tolga
OK. Now let's solve my problem. I'm showing the codes. This will be some long.
Kernel:
=======================================
Code: Select all
extern "C" void isr0();
#include "include\dtables.h"
int main(void)
{
tidt idt;
idt.install_idtr();
idt.set_idt_item( 0, 0x08, (unsigned)isr0, 0x8E );
}
DTABLES.H
=====================================
Code: Select all
// DESCRIPTOR TABLES HEADER FILE
#ifndef __DTABLES_H
#define __DTABLES_H
//||======================
//|| IDT CLASS
//||======================
// Idt Pointer Struct
//=======================
struct tidt_pointer{
unsigned short limit;
unsigned int base;
}__attribute((packed));
// Idt Item Struct
//===========================
struct tidt_item{
unsigned short base_low;
unsigned short selector;
unsigned char always_zero;
unsigned char flags;
unsigned short base_high;
}__attribute((packed));
// Class
//===========================
class tidt{
private:
public:
// Variables
struct tidt_pointer idt_pointer;
struct tidt_item idt_items[256];
// Constructor
tidt();
// Destructor
~tidt();
void set_idt_item( unsigned char int_number, unsigned short selector, unsigned int base, unsigned char flags );
void set_idtr( unsigned int base, unsigned short limit );
void install_idtr();
};
#endif
DTABLES.CPP
====================================
Code: Select all
// DESCRIPTOR TABLES
// Includes
//===========================
#include "dtables.h"
// Externs
//===========================
extern "C" void set_idtr_value();
// Variables
//===========================
// Assembly Extern Variables ( Variable Names Constant )
unsigned int new_idtr_limit;
unsigned int new_idtr_base;
//||=======================================================
//|| IDT CLASS CODES
//||=======================================================
// Constructor
tidt::tidt()
{
}
// Destructor
tidt::~tidt()
{
}
// Set Idt Item
void tidt::set_idt_item( unsigned char int_number, unsigned short selector, unsigned int base, unsigned char flags )
{
// Interrupt Base Address
this->idt_items[ int_number ].base_low = (base & 0xFFFF);
this->idt_items[ int_number ].base_high = (base >> 16) & 0xFFFF;
// Selector
this->idt_items[ int_number ].selector = selector;
// Always Zero Area
this->idt_items[ int_number ].always_zero = 0;
// Present, DPL, System, Type
this->idt_items[ int_number ].flags = flags;
}
// Set IDTR
void tidt::set_idtr( unsigned int base, unsigned short limit )
{
// Load class values
this->idt_pointer.base = base;
this->idt_pointer.limit = limit;
// Load extern values
new_idtr_base = base;
new_idtr_limit = limit;
// Call
set_idtr_value();
}
// Install IDTR
void tidt::install_idtr()
{
// Load class value
this->idt_pointer.base = (unsigned int)&idt_items;
this->idt_pointer.limit = 256 * 8 - 1;
// Load extern values
new_idtr_base = (unsigned int)&idt_items;
new_idtr_limit = 256 * 8 - 1;
// Call
set_idtr_value();
}
SET_IDTR_CODE
====================================
Code: Select all
; Preprocessor
;============================
[BITS 32]
[global start]
[extern _main]
; Main Codes
;============================
section .text
start:
; Now In Loader
mov edi, 0xB8000
mov byte[edi+0], '+'
mov byte[edi+1], 0x07
; Stack
mov esp, SYSTEM_STACK
; C Calling
sti
call _main
; Halt System
cli
hlt
; Variables
;============================
section .data
; IDTR
IDTR:
IDTR_LIMIT DW 0
IDTR_BASE DD 0
; Extern Functions
;============================
section .text
; Set IDTR Value
global _set_idtr_value
extern _new_idtr_limit
extern _new_idtr_base
_set_idtr_value:
pushad
push gs
push fs
push es
push ds
; Load Values
mov eax, dword[_new_idtr_limit]
mov ebx, dword[_new_idtr_base]
mov word[IDTR_LIMIT], ax
mov dword[IDTR_BASE], ebx
; Load New IDTR
lidt [IDTR]
pop ds
pop es
pop fs
pop gs
popad
ret
; Interrupt Service Routines
;============================
global _isr0
; 0: Divison Error
_isr0:
pushad
push gs
push fs
push es
push ds
pop ds
pop es
pop fs
pop gs
popad
iret
; System Stack
;============================
SECTION .bss
resb 8190
SYSTEM_STACK:
Re:Division Error to Reboot
Posted: Mon Jun 12, 2006 6:22 pm
by Cjmovie
Code: Select all
; 0: Divison Error
_isr0:
pushad
push gs
push fs
push es
push ds
pop ds
pop es
pop fs
pop gs
popad
iret
That code is just going to return without touching anything. Excuse me if I'm wrong (I haven't OS-Dev'ed in at least a year), when it returns from the handler, the processor assumes that the handler has fixed the problem. It therefore tries to continue execution at the instruction it left off on - the divide-by-zero. Upon seeing this again, the processor decides your handler doesn't work, attempts to double-fault, which it finds doesn't help, so it triple-faults and resets. You'll have to either add code in there to skip over the instruction (very patchy....in the future, it should terminate the currently running process that caused the problem) or stop EVERYTHING: that means, don't return from the handler, print out a stack dump, and the register data.
*edit*
Tip: try inserting a 'hlt' instruction between the push's and the pop's. It should stop it from reseting, but still just sit there and do nothing.
Re:Division Error to Reboot
Posted: Mon Jun 12, 2006 6:57 pm
by blip
I'm pretty sure the fault would occur infinitely instead of double-faulting the second time around. Double faults only occur when something happens before the first instruction of a handler can be executed for some reason. Also unless an interrupt gate is used to dispatch the handler a CLI instruction will be needed before the HLT. At least if the processor freezes then you know execution has probably reached that point but I think there's some other problem (haven't looked looked at the code in-depth).