ISR Problem
ISR Problem
Hi!
I have a problem with my ISR code. I'm trying to write a simple code for TIMER interrupt, which will just put "T" on the screen (for testing).
However, it does put some number of "T"'s then couple of other symbols and then resets bochs, if I avoid using "iret" instruction
when I use IRET is simply resets bochs after putting one "T".
what could be the reason for that?
I have a problem with my ISR code. I'm trying to write a simple code for TIMER interrupt, which will just put "T" on the screen (for testing).
However, it does put some number of "T"'s then couple of other symbols and then resets bochs, if I avoid using "iret" instruction
when I use IRET is simply resets bochs after putting one "T".
what could be the reason for that?
It sounds like something is wrong with your code (I dont think your timer, though.) Its hard to tell without code...
When Bochs resets (triple faults), can you also post the log output from Bochs?
Also the code for your interrupt routine might be helpful.
When Bochs resets (triple faults), can you also post the log output from Bochs?
Also the code for your interrupt routine might be helpful.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Your code would indeed be helpful.
do you push all core registers before executing your ISR and then restore them after?
do you push all core registers before executing your ISR and then restore them after?
Website: https://joscor.com
Oh, yeps ... Sorry, I've forgotttten the code part ...
The bochs log: http://users.evtek.fi/~aleksanc/osdev/bochsout.txt
Also the rest of the src files ... just in case:
http://users.evtek.fi/~aleksanc/osdev/src/
In case this is relevant, my dev-environment is:
Win Vista ( )
Bochs x86 Emulator 2.3.6
GCC (4.2.2) [DJGPP]:
gcc -v output:
GNU ld version 2.17
Code: Select all
#define PIC1 0x20
#define PIC2 0xA0
#define PIC_EOI 0x20
inline void irq_timer(void){
asm ("pusha");
asm ("mov %ds, %ax");
asm ("push %eax");
asm ("mov $0x8, %ax");
asm ("mov %ax, %ds");
asm ("mov %ax, %fs");
asm ("mov %ax, %gs");
puts ("T");
//outportb (PIC1, PIC_EOI);
asm ("pop %eax");
asm ("mov %ax, %ds");
asm ("mov %ax, %es");
asm ("mov %ax, %fs");
asm ("mov %ax, %gs");
asm ("popa");
asm ("add $0x8, %esp");
asm ("sti");
asm ("iret");
}
Also the rest of the src files ... just in case:
http://users.evtek.fi/~aleksanc/osdev/src/
In case this is relevant, my dev-environment is:
Win Vista ( )
Bochs x86 Emulator 2.3.6
GCC (4.2.2) [DJGPP]:
gcc -v output:
Code: Select all
Configured with: /v203/gcc-4.22/configure djgpp --prefix=/dev/env/DJDIR --disable-nls --disable-werror --enable-languages=c,c++,fortran,objc,obj-c++,ada
Thread model: single
gcc version 4.2.2
Also, I though when trying to avoid gcc-asm conflictions, shouldn't you use the __asm__ __volatile__ assignment?
Website: https://joscor.com
Also, why do sti before iret? iret will pop eflags from the stack anyway (hence returning the IF flag to its pre-interrupt value), so this is redundant and a little dangerous (you're going to get nested interrupts).
Oh, and according to your bochsout.txt, you are in real mode. Do segment selectors even apply here? I'm sure segments are a part of the actual address in real mode.
Oh, and according to your bochsout.txt, you are in real mode. Do segment selectors even apply here? I'm sure segments are a part of the actual address in real mode.
Code: Select all
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M/MU d- s:- a--- C++++ UL P L++ E--- W+++ N+ w++ M- V+ PS+ Y+ PE- PGP t-- 5- X R- tv b DI-- D+ G e h! r++ y+
------END GEEK CODE BLOCK------
TO me the problem was kind of obvious.
It is failing with the iret immediately because gcc pushed the old ebp value to the stack.
It fails without the iret because slowly by slowly, you're stack pointer keeps on decreasing, overwrites something else and finally either comes a an unmapped region(if you're using paging) or overwrites your code with garbage which then gives you some sort of error.
The solution is to scrap the inline assembly and use pure assembly to enter and exit the interrupt.
For example a good way to do irqs is the following
Note that the above code pushes a structure onto the stack that you can either ignore or use as the first argument to your function.
The structure is as follows:
The vm_* fields are used in vm8086 mode and refer to the segment selectors pushed by the processor in that mode. These fields are invalid in any other mode. Also, the useresp and ss fields are invalid in interrupts received in kernel mode.
Hope that helps.[/code][/i]
It is failing with the iret immediately because gcc pushed the old ebp value to the stack.
It fails without the iret because slowly by slowly, you're stack pointer keeps on decreasing, overwrites something else and finally either comes a an unmapped region(if you're using paging) or overwrites your code with garbage which then gives you some sort of error.
The solution is to scrap the inline assembly and use pure assembly to enter and exit the interrupt.
For example a good way to do irqs is the following
Code: Select all
irq_handler_stub:
pusha
push %ds
push %es
push %fs
push %gs
push %ss
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
mov %esp, %eax
push %eax
call <any-function>
pop %eax
pop %ss
pop %gs
pop %fs
pop %es
pop %ds
popa
iret
The structure is as follows:
Code: Select all
typedef struct regs_t
{
unsigned int r_ss, gs, fs, es, ds; /* pushed the segs last */
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */
unsigned int int_no, err_code; /* our 'push byte #' and ecodes do this */
unsigned int eip, cs, eflags, useresp, ss; /* pushed by the processor automatically */
unsigned int vm_es, vm_ds, vm_fs, vm_gs;
} regs;
Hope that helps.[/code][/i]