hi there!
i've now coded my first-state-os to gcc & fasm, but i encounter problems when i want to write the service routines. is it possible to tell gcc that it sould preserve all used registers and use "iret" instead of "ret" at the end?
i tried the __attribute__-thingy, but i get a warning that the interrupt-attribute was ignored...
greets, hartyl
interrupt handler & gcc
RE:interrupt handler & gcc
The gcc info says about the interrupt function attribute , "Use this attribute on the ARM, AVR, M32R/D and Xstormy16 ports . . .". It doesn't mention x86 (which I assume you're using), so it probably isn't for the x86. If you want to use C/C++ functions for your interrupts, you'll probably have to write a little function stub in assembly that pushes all registers, calls the C routine, pops all registers and does an iret. Either that, or you'll have to use a compiler that supports x86 interrupts directly. I recommend the first idea. But I would actually recommend writing the simplest interrupt routines completely in assembly.
RE:interrupt handler & gcc
My gcc isr looks like:
#define CLI asm("cli")
#define IRET("leave\n iret")
#define STI asm("sti")
void Isr0x(void)
{
CLI
do_something();
STI
IRET
}
and works fine.
Note the leave and no parameters to isr
I set the isr in IDT just passing the pointer to ISR to my SetInterruption rountine
#define CLI asm("cli")
#define IRET("leave\n iret")
#define STI asm("sti")
void Isr0x(void)
{
CLI
do_something();
STI
IRET
}
and works fine.
Note the leave and no parameters to isr
I set the isr in IDT just passing the pointer to ISR to my SetInterruption rountine
RE:interrupt handler & gcc
yeah, that the thing i'm somehow afraid of.
when you do it like that you somehow have to care about the stack-frame gcc generates. i think i'll do it like you, jcmatias, but i know that the thing will look like this then
isr0x00:
push ebp
mov ebp,esp
sub esp,<someval>
cli
;here's my code
sti
leave
iret
pop ebp ;gcc still generates the clean-up
ret ;-code after your code
it's also interesting: when you change the optimisation-level it will sometimes not use a stack-frame, and that your ISR-leave-and-iret-thing won't work anymore...
when you do it like that you somehow have to care about the stack-frame gcc generates. i think i'll do it like you, jcmatias, but i know that the thing will look like this then
isr0x00:
push ebp
mov ebp,esp
sub esp,<someval>
cli
;here's my code
sti
leave
iret
pop ebp ;gcc still generates the clean-up
ret ;-code after your code
it's also interesting: when you change the optimisation-level it will sometimes not use a stack-frame, and that your ISR-leave-and-iret-thing won't work anymore...
RE:interrupt handler & gcc
you're absolute light hartyl. With typical settings, that's the result. With -O2 and -fomit-frame-pointer it seems to consistantly move the stack setup to directly before usage. (-O3 it inlines too much to be usable with inline asm).
anyway, the way i apprached this is like this:
void isr00(void) {
__asm__ __volatile__ ("cli");
// do stuff
__asm__ __volatile__ ("sti");
__asm__ __volatile__ ("iret");
}
now what this tends to do is create code _just before_ the "do stuff" and put the cleanup just after the "iret" emitted. So i look at the kernel.lst file my mkaefile generates (usually just an "add %esp, $0x08" or somthing) and put the inline code for that directly _after_ the do stuff. It is definitely workable, but it will be very compiler _and_ setting specific.
The reason why you want the restor code exactly after the do stuff and the setup directly before, is so yo ucan use push and pop operations elsewhere in the routine (such as saving segment values) without trashing things.
Keep in mind, that for this to work, you must use very specific optimization settings...
Also note, that i am planning on redoing my ISRs in ASM because this is too annoying for me
proxy
anyway, the way i apprached this is like this:
void isr00(void) {
__asm__ __volatile__ ("cli");
// do stuff
__asm__ __volatile__ ("sti");
__asm__ __volatile__ ("iret");
}
now what this tends to do is create code _just before_ the "do stuff" and put the cleanup just after the "iret" emitted. So i look at the kernel.lst file my mkaefile generates (usually just an "add %esp, $0x08" or somthing) and put the inline code for that directly _after_ the do stuff. It is definitely workable, but it will be very compiler _and_ setting specific.
The reason why you want the restor code exactly after the do stuff and the setup directly before, is so yo ucan use push and pop operations elsewhere in the routine (such as saving segment values) without trashing things.
Keep in mind, that for this to work, you must use very specific optimization settings...
Also note, that i am planning on redoing my ISRs in ASM because this is too annoying for me
proxy
RE:interrupt handler & gcc
what you really want, is an ASM stub
isr00:
stub setup
call d[_isr_00_jump]
stub cleanup
iret
repeat for all isrss etc.
and in you C code you can then set isr to anything (just put the address of the function into the _isr_00_jump array
setisr(void *isrroutine, int isr)
{
my_isr_jump_table[isr] = isrroutine;
}
semi psuedo c/asm code
its pretty rough, but you get the idea on how to use it.
I'm also _EXTREMLY_ against trying to do the isr in C with inline asm. its a lot easier + cleaner to do it in an asm stub, and correctly setup an isr, sane segment registers/stack whatever.
isr00:
stub setup
call d[_isr_00_jump]
stub cleanup
iret
repeat for all isrss etc.
and in you C code you can then set isr to anything (just put the address of the function into the _isr_00_jump array
setisr(void *isrroutine, int isr)
{
my_isr_jump_table[isr] = isrroutine;
}
semi psuedo c/asm code
its pretty rough, but you get the idea on how to use it.
I'm also _EXTREMLY_ against trying to do the isr in C with inline asm. its a lot easier + cleaner to do it in an asm stub, and correctly setup an isr, sane segment registers/stack whatever.
-- Stu --
RE:interrupt handler & gcc
ya, i now found out the problems. when enabling the optimisation, the ISR don't work anymore since the stack gets screwed up.
i somehow don't like using assembler-code for the isr which calls my c-routine. it blows up the code. however, its the universal version which works with every compiler-switches.
i somehow don't like using assembler-code for the isr which calls my c-routine. it blows up the code. however, its the universal version which works with every compiler-switches.
RE:interrupt handler & gcc
.
.
.
pop ebp ; gcc still generates the clean-up
ret ; -code after your code
never will be executed. This is after IRET. The stack is cleaned by LEAVE
( I omit, but isr don't have any local data (if you need declare vars use "static" types ).
.
.
pop ebp ; gcc still generates the clean-up
ret ; -code after your code
never will be executed. This is after IRET. The stack is cleaned by LEAVE
( I omit, but isr don't have any local data (if you need declare vars use "static" types ).