Page 1 of 2
Turbo C trouble with Interrupt Vector Table..
Posted: Sun Jun 14, 2009 8:37 pm
by Risc
Hello fellow OS developers!
My name is Risc and I'm new to these forums.
I am developing a small real mode kernel in Turbo C (v2 i think... the first 'blue' version) and have run into a problem.
This piece of code is driving me nuts. The INT_0 interrupt function is never called when I divide by zero. The system just hangs.
Code: Select all
void interrupt INT_0()
{
printf("Interrupt 0\r\n");
}
void install_interrupts()
{
int int0 = (int)INT_0;
/* I have tried with:
int* int0 = (int*)INT_0; */
/* Zero extra segment */
asm xor ax, ax
asm mov es, ax
/* Intel-specific interrupts */
asm mov dx, int0
asm mov WORD [es:0x0], dx /* Add the Interrupt procedure location to the IVT */
asm mov WORD [es:0x02], cs /* Segment containing the procedure */
asm sti
}
I would appreciate any input.
Thanks.
/Risc
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Sun Jun 14, 2009 8:58 pm
by Troy Martin
Hmm, try adding push es before xor ax,ax and pop es after sti (and you don't really need sti in there.)
EDIT: Why does interrupt 0 return? And why don't you setup printf to make \n the same as \r\n?
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Sun Jun 14, 2009 9:03 pm
by kop99
Risc, if you have any bochs logs, then post that.
And do you load idtr?
So, post that code.
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Sun Jun 14, 2009 9:04 pm
by Troy Martin
kop: the IDTR is pmode; Turbo C does crap in real mode.
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 2:42 am
by Risc
Troy Martin wrote:Hmm, try adding push es before xor ax,ax and pop es after sti (and you don't really need sti in there.)
Yes, I removed the boiler plate code for easier reading. That doesn't help unfortunately.
Troy Martin wrote:EDIT: Why does interrupt 0 return?
Borland C compilers have a special "interrupt" preprocessor tag you insert in front of function names to make the compiler
push all registers, do whatever is inside of that function,
pop all registers and finally
iret.
It doesn't return in a normal fashion.
Troy Martin wrote:And why don't you setup printf to make \n the same as \r\n?
Maybe I will, when I get around this
kop99 wrote:Risc, if you have any bochs logs, then post that.
And do you load idtr?
So, post that code.
Sorry but I don't use bochs (probably a stupid idea not to!). I've been trying out my kernel in VirtualBox, which is pretty worthless since I get no debugging capabilities. If anyone would like to elaborate on how to mount a floppy in bochs (I don't like rebuilding the image each time I recompile) I would be grateful.
EDIT: I strongly believe that the following lines are a cause of the problem.
Code: Select all
asm mov dx, int0
asm mov WORD [es:0x0], dx /* Add the Interrupt procedure location to the IVT */
In pure assembler (NASM) I would have written:
Code: Select all
mov WORD [es:0x0], INT_0 /* Add the Interrupt procedure location to the IVT */
I don't know how to do that in TASM since it expects the second argument to be a register (note that int0 and INT_0 are two different things)...
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 4:26 am
by ru2aqare
Risc wrote:
EDIT: I strongly believe that the following lines are a cause of the problem.
Code: Select all
asm mov dx, int0
asm mov WORD [es:0x0], dx /* Add the Interrupt procedure location to the IVT */
In pure assembler (NASM) I would have written:
Code: Select all
mov WORD [es:0x0], INT_0 /* Add the Interrupt procedure location to the IVT */
I don't know how to do that in TASM since it expects the second argument to be a register (note that int0 and INT_0 are two different things)...
Try
or even
Code: Select all
push cs
push offset INT_0
pop word ptr es:[0]
pop word ptr es:[2]
TASM and compatibles have the offset keyword (which NASM lacks unfortunately).
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 6:41 am
by jal
Risc wrote:asm mov dx, int0
TC might well be assigning the
address of int0 to dx.
I would appreciate any input.
It's rather simple to debug I would say. Print the address of the INT_0 routine, and what is found at 0000:0000 to see if they match.
JAL
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 8:46 am
by Troy Martin
Risc wrote:It doesn't return in a normal fashion.
It shouldn't return in any fashion; interrupt 0 is a divide error exception, meaning the return IP points to the offending address. That way, when it returns, it divides again, making it go "zOMG!" and fire exception 0 again.
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 9:36 am
by earlz
ru2aqare wrote:Risc wrote:
EDIT: I strongly believe that the following lines are a cause of the problem.
Code: Select all
asm mov dx, int0
asm mov WORD [es:0x0], dx /* Add the Interrupt procedure location to the IVT */
In pure assembler (NASM) I would have written:
Code: Select all
mov WORD [es:0x0], INT_0 /* Add the Interrupt procedure location to the IVT */
I don't know how to do that in TASM since it expects the second argument to be a register (note that int0 and INT_0 are two different things)...
Try
or even
Code: Select all
push cs
push offset INT_0
pop word ptr es:[0]
pop word ptr es:[2]
TASM and compatibles have the offset keyword (which NASM lacks unfortunately).
you could also try something like
Code: Select all
mov dx,word ptr [int0]
mov WORD [es:0x0], dx
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 10:38 am
by mathematician
Which Memory Model are you using?
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 12:31 pm
by Combuster
use getvect() and setvect(), turbo C has them for a reason.
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 4:27 pm
by mathematician
Combuster wrote:use getvect() and setvect(), turbo C has them for a reason.
Assuming that they don't call MS-DOS functions 35h (get vector) and 25h (set vector).
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 4:55 pm
by Risc
mathematician wrote:Assuming that they don't call MS-DOS functions 35h (get vector) and 25h (set vector).
It seems that they do unfortunately.
However, ru2aqare's code did the trick! It successfully traps to the correct function.
Now I seem to be having a stack problem or something because I can successfully do printc (print a character) but I can't printf (print a string). In Bochs it looks like printf never calls printc but sits around in an endless loop (remember, normally this works fine, it's just when calling it from the interrupt function). The interrupt function does nothing special btw.
Have a look at the code below:
Code: Select all
void printc(char c)
{
asm push ax
/* Print a character on screen */
asm mov al, c
asm mov ah, 0x0e
asm int 0x10
asm pop ax
}
/* Prints a string */
void printf(char* str)
{
int i = 0;
while(str[i] != '\0')
printc(str[i++]);
}
...
Code: Select all
void interrupt INT_0()
{
/* putc('a'); WORKS */
printf("Hello world\0"); /* No cigar... */
asm hlt
}
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 5:15 pm
by ru2aqare
Code: Select all
void interrupt INT_0()
{
/* putc('a'); WORKS */
printf("Hello world\0"); /* No cigar... */
asm hlt
}
[/quote]
I don't know what assembly code does your TC generate, but you may have to reload (and upon exit from the interrupt function, restore) the segment registers.
Re: Turbo C trouble with Interrupt Vector Table..
Posted: Mon Jun 15, 2009 5:37 pm
by mathematician
Risc wrote:mathematician wrote:Assuming that they don't call MS-DOS functions 35h (get vector) and 25h (set vector).
It seems that they do unfortunately.
However, ru2aqare's code did the trick! It successfully traps to the correct function.
Now I seem to be having a stack problem or something because I can successfully do printc (print a character) but I can't printf (print a string). In Bochs it looks like printf never calls printc but sits around in an endless loop (remember, normally this works fine, it's just when calling it from the interrupt function). The interrupt function does nothing special btw.
Have a look at the code below:
Code: Select all
void printc(char c)
{
asm push ax
/* Print a character on screen */
asm mov al, c
asm mov ah, 0x0e
asm int 0x10
asm pop ax
}
/* Prints a string */
void printf(char* str)
{
int i = 0;
while(str[i] != '\0')
printc(str[i++]);
}
...
Code: Select all
void interrupt INT_0()
{
/* putc('a'); WORKS */
printf("Hello world\0"); /* No cigar... */
asm hlt
}
One thing I notice is that you are forgetting to zero the bh register. bh contains the video page number, and, unless you change it, it is page 0 which appears on the screen.