Page 1 of 2
exceptions are not being caught
Posted: Thu Sep 11, 2003 2:51 am
by Andrew
Hi,
what i am trying to do is to programm my exception handlers, but it is not workin, although i've done eveything according tutorials.
if we insert __asm__("int $0"); line in main function
and run it in bochs, we get such error:
Message: exception(): 3rd (14) exception with no resolution
and running on real PC (from floppy drive) it just keeps restarting
(( so plz help me. it is been 2 days we are searching for the bug, thank you in advance.
/// Int.h
#ifndef _INT_
#define _INT_
#include "../lib/stdio.h"
#include "../lib/Floppy.h"
static __u8 BITMAP1 = 0; // all enabled
static __u8 BITMAP2 = 0; // all enabled
// some structures for irq
// IDT descriptor format
typedef struct
{
unsigned short low_offset;
unsigned short selector;
unsigned short settings; // 15b - Present; 14-13b - Description Privelege Level
unsigned short high_offset;
}Idt;
typedef struct
{
unsigned short limit; // length of the IDT
__u32 base; // address fo the start of the IDT
}IdtP;
extern "C" void lidt(IdtP *);
class Int
{
private:
Idt IDT[256]; // maximum number of descriptors
IdtP IDTR;
...
};
#endif
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 2:58 am
by Andrew
//Int.cpp
#include "../lib/Int.h"
void Int::loadIDT(){
IDTR.limit = 256*(sizeof(Idt)-1);
__u32 _DS; __asm__("movw %%ds, %0 \t\n":"=g"(_DS));
IDTR.base = ((__u32)_DS)<<4;
IDTR.base += (unsigned int) & IDT;
// lidt(&IDTR);
__asm__("lidt (%0) \t\n"::"p"(&IDTR));
}
//void Int::createInt(int num, void (*proc)(), __u16 set){
void Int::createInt(int num, __u32 offset, __u16 set){
__u32 address = offset;
__u16 code_selector;
__asm__("movw %%cs, %0 \t\n":"=g"(code_selector));
IDT[num].low_offset = address & 0xFFFF;
IDT[num].selector = code_selector;
IDT[num].settings = (set==0x8e00)?set:( (set==0xae00)?set:( (set==0xce00)?set:0x8e00 ) );
IDT[num].high_offset = address >> 16;
}
void Int::loadExceptions(){
createInt(0, (unsigned int)&isr0, 0);//and so on
}
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 3:01 am
by Andrew
void Int::intExp(char *message, bool stop){
__asm__("cli"); // testing
__asm__("hlt");
}
extern "C" void int0(void){
Int::intExp("Division by Zero Error", false);
}
//and so on
extern "C" void TimerIRQ(){
Floppy::TickCounter++;
__u8 *scr;
scr = (__u8 *)(0x20*16 + 80*4+8*2);
scr[0]++;
__asm__("outb %%al, %%dx \t\n"::"a"(EOI), "d"(PIC1));
}
extern "C" void FloppyIRQ(){
Floppy::FDD_intFlag = 1;
__asm__("outb %%al, %%dx \t\n"::"a"(EOI), "d"(PIC1));
}
void Int::initInterrupts(){
__asm__("cli \t\n");
disableNMI();
remapPIC(0x20, 0x28);
maskIRQ(ALL);
loadExceptions();
//our hardware interrupts
createInt(32, isr32, 0);
createInt(38, isr38, 0);
//--------------
loadIDT();
unmaskIRQ(ALL);
enableNMI();
__asm__("sti \t\n");
}
//isr.asm
[extern _int0]
[global _isr0]
_isr0:
pusha
push gs
push fs
push ds
push es
mov ax, 10h
mov ds, ax
mov es, ax
cld
call _int0 ;Divide Error
pop es
pop ds
pop fs
pop gs
popa
iret
; and so on
; IRQ's
[extern _TimerIRQ]
[global _isr32]
_isr32:
pusha
push gs
push fs
push ds
push es
push ax
mov ax, 10h
mov ds, ax
mov es, ax
call _TimerIRQ ;testing
push ax
pop es
pop ds
pop fs
pop gs
popa
iret
[extern _FloppyIRQ]
[global _isr38]
_isr38:
pusha
push gs
push fs
push ds
push es
mov ax, 10h
mov ds, ax
mov es, ax
cld
call _FloppyIRQ ;testing
pop es
pop ds
pop fs
pop gs
popa
iret
[global _lidt]
_lidt:
push bp
mov bp, sp
push bx
mov bx, [ss:bp+4] ; ds:bx = pointer to IDTR structure
lidt [ds:bx] ; load IDTR
pop bx
pop bp
retn
i would be really appreciated if you took a look at my code and gave me a hint how to solve my problem.
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 4:20 am
by Pype.Clicker
okay, first ... please register to this forum, so that you'll be able to post your code rather than flooding a thread with poorly formatted code (there's a [ code ] [ /code ] style for short code fragments).
second. I'm afraid you have *not* "done eveything according tutorials" ... For instance:
Code: Select all
typedef struct
{
unsigned short limit; // length of the IDT
__u32 base; // address fo the start of the IDT
}IdtP;
has little chance to follow the 6 bytes packing intel requires. Instead, the compiler will actually implement the structure as
Code: Select all
{
unsigned short limit;
short padding;
__u32 base;
}IdtP;
so that base will be 4bytes-aligned. Check your compiler's documentation to know how you can get around this. A possible trick is to put padding *then* limit and to tranmit
((void*)&IDTR)+2 to your lidt instruction.
Fix this first: until you have a valid IDTR, you cannot receive exception correctly.
third, please, for the sake of readability, consider declaring "outb()" and "inb()" macros rather than using ASM() commands everywhere... And if i were you, i would *not* restore the old masks after remapping because you're not sure of what interrupt you will receive. Unmask interrupts one by one, when you install handlers for them.
fourth (damn, i didn't plan to go that far), you should *not* issue several asm() commands and expect register values to be preserved from on to another.
Code: Select all
void Int::disableNMI(){
__asm__("inb %%dx, %%al \t\n"::"d"(0x70));
__asm__("andb 0x7f, %al \t\n");
__asm__("outb %%al, %%dx \t\n"::"d"(0x70));
}
should rather be written
Code: Select all
void Int::disableNMI(){
__asm__ volatile("inb %%dx, %%al \t\nandb 0x7f, %al \t\noutb %%al, %%dx \t\n"::"d"(0x70));
}
The 'volatile' keyword will force the compiler to issue the assembler statement even if it thinks these commands may be omitted for optimization purpose.
or better:
Code: Select all
//io.h
static inline __u8 inb(__u16 port)
{
__u8 val;
__asm__ volatile("inb %1, %0":"=a"(val):"d"(port));
}
// your file
void Int::disableNMI() {
outb(0x70,inb(0x70)&0x7f);
}
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 4:56 am
by Andrew
thank you for your post it is really informative.
i'm really sorry i didn't mean to flood. and i'll register later.
i'd like to ask a question about padding field (i found nothing about it in my tutorial). What should be values of this field?
thank you in advance.
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 6:12 am
by Solar
Andrew wrote:
i'd like to ask a question about padding field (i found nothing about it in my tutorial). What should be values of this field?
Since
((void*)&IDTR)+2 will skip the padding field, the value doesn't matter at all. Best leave it uninitialized, since initialisation would imply you are actually using the value for something (which you don't).
You have understood the issue of padding / field alignment in general, haven't you?
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 6:41 am
by Andrew
now i did, thanks
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 11:16 am
by Andrew
came home and tried out your suggestions:
i didn't add field padding into structure IdtP
changed the line
lidt(&IDT); (which was commented)
into
lidt(((void *)&IDT)+2);
and got the error :
pointer of type `void *' used in arithmetic.
tried lidt(((unsigned char *)&IDT)+2); but still no exception caught
d*mn, what i am doing wrong
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 11:48 am
by Pype.Clicker
if you do not convert your structure to
Code: Select all
{
unsigned short padding;
unsigned short limit;
unsigned base;
} Idtp;
adjusting the address is useless ...
Re:exceptions are not being caught
Posted: Thu Sep 11, 2003 3:07 pm
by Andrew
well i added unsigned short padding; to my structure
and loaded idt this way:
__asm__("lidt (%0) \t\n"::"p"(((unsigned char*)&IDTR)+2));
but it didn't solve the problem, exception is not caught.
plz take a look at my code maybe i missed smth.
[attachment deleted by admin]
Re:exceptions are not being caught
Posted: Fri Sep 12, 2003 1:23 am
by Pype.Clicker
but it didn't solve the problem, exception is not caught.
What could make you think the exception is/is not caught. What exactly occurs ??
btw, what is that
Code: Select all
__u32 _DS; __asm__("movw %%ds, %0 \t\n":"=g"(_DS));
IDTR.base = ((__u32)_DS)<<4;
in your code ? "everything from the tutorial", eh ? well, imho, your tutorial was programming the IDT from
real mode while you're programming it from
protected mode.
In protected mode, the selector for the datasegment is no longer base/16, so instead of having
IDTR.base = _DS<<4, you should rather have
IDTR.base = GDT.getFromSelector(_DS).getBase() ...
Re:exceptions are not being caught
Posted: Fri Sep 12, 2003 6:24 am
by Andrew
but it didn't solve the problem, exception is not caught.
What could make you think the exception is/is not caught. What exactly occurs ??
i do this
Code: Select all
int a; int b; b = 1; a = 0; b = b/a;
btw, what is that
Code: Select all
???__u32 _DS; __asm__("movw %%ds, %0 \t\n":"=g"(_DS));
???IDTR.base = ((__u32)_DS)<<4;
actually my code is
Code: Select all
__u16 _DS; __asm__("movw %%ds, %0 \t\n":"=g"(_DS));
IDTR.base = ((__u32)_DS)<<4;
IDTR.base += (unsigned int) & IDT;
and i am trying to load a linear address of the first IDT element
In protected mode, the selector for the datasegment is no longer base/16, so instead of having IDTR.base = _DS<<4, you should rather have IDTR.base = GDT.getFromSelector(_DS).getBase() ...
what that function getFromSelector should do? and why should i load the base of GDT instead of IDT?
Re:exceptions are not being caught
Posted: Fri Sep 12, 2003 6:56 am
by Pype.Clicker
The linear address of your IDT is "offset of IDT within the current data segment" (which is &IDT) + "base address for that data segment".
In protected mode, where's the base of your data segment ? in your GDT.
So first find back the descriptor of your data segment (i assumed you had
Code: Select all
class DescriptorTable {
Descriptor entries[];
getFromSelector(word selector) {
// throw BadTableException if bit 1 is set.
// throw BadSelectorException if selector is beyond limit
return entries[selector>>3];
}
}
) and then retrieve the base address of that data segment (using
Code: Select all
struct Descriptor {
union {
byte b[8];
word w[4];
} raw;
getLimit() {
return raw.w[0]+...;
}
getBase() {
return raw.w[1] + (raw.b[4]<<16) + (raw.b[7]<<24);
}
};
).
Hope it's clearer now ...
Re:exceptions are not being caught
Posted: Fri Sep 12, 2003 11:03 am
by Andrew
i did this:
loaded gdt this way:
Code: Select all
[BITS 32]
[global _loadGDT]
_loadGDT:
lgdt [gdt_ptr]
mov ax, DATA_SELECTOR
mov ds, ax
mov es, ax
mov ss, ax
mov fs, ax
mov gs, ax
retn
SECTION .data
gdt_start:
;null sectio
dw 0
dw 0
db 0
db 0
db 0
db 0
;not used because of some reasons :)
dw 0
dw 0
db 0
db 0
db 0
db 0
; DATA
DATA_SELECTOR EQU $-gdt_start
dw 0ffffh
dw 0
db 0
db 92h
db 0xCF
db 0
; CODE
CODE_SELECTOR EQU $-gdt_start
dw 0ffffh
dw 0
db 0
db 9ah
db 0xCF
db 0
gdt_end:
gdt_ptr:
dw gdt_end - gdt_start - 1
dd gdt_start
IdtP structure looks like
Code: Select all
typedef struct
{
???unsigned short padding;
unsigned short limit; // length of the IDT
__u32 base; // address fo the start of the IDT
}IdtP;
IDT i load this way now:
Code: Select all
void Int::loadIDT(){
???IDTR.limit = 256*(sizeof(Idt)-1);
???IDTR.base = (unsigned int)&IDT; // + base address from gdt (but i use 0)
???__asm__("lidt (%0) \t\n"::"p"(((__u8*)&IDTR)+2));
}
and the main procedure looks like this
Code: Select all
???__asm__("cli \t\n");
???disableNMI();
???loadGDT();
???remapPIC(0x20, 0x28); ???
???maskIRQ(ALL);
???loadExceptions();
//our hardware interrupts
??????createInt(32, (unsigned int)isr32, 0);
??????createInt(38, (unsigned int)isr38, 0);
//--------------
???unmaskIRQ(0); unmaskIRQ(6);
???loadIDT();
???enableNMI();
???__asm__("sti \t\n");
and it is not working d*mn, now what is wrong
i check division by zero this way
Code: Select all
int a;
int b;
a = 0;
b = 1;
b = 1/a;
and bochs tells me :
Message: exception(): 3rd (13) exception with no resolution
P.S. maybe this is incorrect?
Code: Select all
void Int::createInt(int num, __u32 offset, __u16 set){
???__u32 address = offset;
???__u16 code_selector;
???__asm__("movw %%cs, %0 \t\n":"=g"(code_selector));
???IDT[num].low_offset = address & 0xFFFF;
???IDT[num].selector = code_selector;
???IDT[num].settings = (set==0x8e00)?set:( (set==0xae00)?set:( (set==0xce00)?set:0x8e00 ) );
???IDT[num].high_offset = address >> 16;
}
//.....
createInt(0, (unsigned int)&isr0, 0);
Re:exceptions are not being caught
Posted: Sat Sep 13, 2003 3:47 pm
by Andrew
d*mn, i am starting to think that it is impossible to solve this problem. ??? maybe you know some commercial emulators whit trial that could give a hint on solving the problem or smth like that.
'cause bochs : Message: exception(): 3rd (13) exception with no resolution
tells me nothing.
[attachment deleted by admin]