Page 1 of 3
iret error
Posted: Wed Jun 04, 2008 10:51 am
by suthers
I'm getting an error in my ISR when it does the iret.
I get:
fetch_raw_descriptor: LDTR.valid=0
This means that my stack frame is probably messed up as Its getting a wrong descriptor.
So i decided to pop the top of the stack into my registers at different points to see if there are changes.
I popped them in the order: eax, ebx, ecx, edx, esi, ebp, edi.
So if I do this at the beginning I get:
EAX=00100459
EBX=00000008
ECX=00010246
EDX=00000034
ESI=0000000a
EBP=001002a4
EDI=00100486
and if I do it at the end I get:
EAX=00100449
EBX=00000008
ECX=00010246
EDX=00000034
ESI=0000000a
EBP=001001a4
EDI=00100476
So there doesn't seem to be much change (weird that there is change later in the stack...)
Anybody know why this happening, couldn't figure it out....
Thanks in advance,
Jules
edit: put registers in order of popping for ease of reading... and a bit of spelling fix...
Posted: Wed Jun 04, 2008 11:40 am
by neon
You should use iretd instead of iret for 32 bit code.
Posted: Wed Jun 04, 2008 12:00 pm
by suthers
nasm automatically converts it to iretd if your in 32bit code.
But I still can't see what would cause the iretd to fail...
Anybody?
Thanks in advance,
Jules
Posted: Wed Jun 04, 2008 12:04 pm
by Combuster
try the combination of bochs, debugger, and the print-stack command
Posted: Wed Jun 04, 2008 12:50 pm
by suthers
Weird, the version of bochs I normally use (2.0.2) only prints "Exception: divide by zero" once, as it should, but the new version (2.3.6) I got to be able to do dbg prints it out loads of times, yet theres no loop in the code and only a single divide by zero in the code (and anyway it only ever does the interrupt once because of the LDTR error...).
Thanks, Combuster, that helps allot, it gave me this:
Code: Select all
| STACK 0x0000 [0xff55]
| STACK 0x0002 [0xf000]
| STACK 0x0004 [0xff53]
| STACK 0x0006 [0xf000]
| STACK 0x0008 [0xff53]
| STACK 0x000a [0xf000]
| STACK 0x000c [0x0053]
| STACK 0x000e [0xf007]
| STACK 0x0010 [0x0700]
| STACK 0x0012 [0x2f00]
| STACK 0x0014 [0xff53]
| STACK 0x0016 [0xf000]
| STACK 0x0018 [0xff53]
| STACK 0x001a [0xf000]
| STACK 0x001c [0xff53]
| STACK 0x001e [0xf000]
If I let it run till error
But that looks like the top off the stack after the iret has removed the top of it...
Anybody see what im doing wrong, ive made sure theres a pop for every push, etc...
Here's the isr's code:
Code: Select all
_isr:
mov [store_1], eax
pop eax
mov [store_2], eax
mov eax, [store_1]
pusha
push es
push ds
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, _int_handler
mov ebx, [store_2]
push ebx
call eax
pop eax
pop gs
pop fs
pop ds
pop es
popa
add esp, 4
sti
iret
...
SECTION .data
...
store_1 dd 0
store_2 dd 0
Its called by stubs that look like this:
Code: Select all
_isr0:
cli
hlt
push byte 0
push byte 0
jmp _isr
_isr1:
cli
push byte 0
push byte 1
jmp _isr
...
numbered 0 - 31.
and the int handler looks like this:
Code: Select all
void int_handler(int err_code)
{
k_printf(exception_messages[err_code], 0x04);
return;
};
everything compiles/assembles/links with no errors/warnings (except compile warning: "warning: division by zero", but that's done on purpose to trigger an interrupt).
Can't see what I'm doing wrong...
Anybody see what's wrong with it?
Thanks in advance,
Jules
P.S. Sorry for dumping so much code... (But there's been worse...)
edit: changed Dex to Combuster, I always get confused because you use a picture of dexter from the cartoon dex's lab as your avatar, sorry...
second edit: thanks for the tip Combuster, that can be really useful
Posted: Wed Jun 04, 2008 4:42 pm
by Combuster
Is that the stack before the iret, or after? If it's from before, why are you running code in 16-bit mode?
Posted: Wed Jun 04, 2008 4:47 pm
by suthers
Its from after an I'm definitely in 32bit protected mode.
Still can't figure out what's wrong and I can't find a doc on the structure of the LDTR(though if I looked carefully in the Intel manuals i'll probably find it...), so I'm not quite sure why I'm getting an LDTR invalid error...
Thanks in advance,
Jules
Posted: Wed Jun 04, 2008 7:47 pm
by Dex
Does this still crash ?.
Code: Select all
_isr:
mov [store_1], eax
pop eax
mov [store_2], eax
mov eax, [store_1]
pusha
push es
push ds
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax,esp
push eax
mov eax, _int_handler
mov ebx, [store_2]
call eax
pop eax
pop gs
pop fs
pop ds
pop es
popa
add esp, 4
iret
or this:
Code: Select all
_isr:
pop eax
mov [store_1], eax
pop eax
mov [store_2], eax
mov eax, [store_1]
pusha
push es
push ds
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax,esp
push eax
mov eax, _int_handler
mov ebx, [store_2]
call eax
pop eax
pop gs
pop fs
pop ds
pop es
popa
iret
Posted: Thu Jun 05, 2008 4:29 am
by suthers
Whats the point in that, all it does is passes the a pointer to the place where the contence of gs is on the stack to the function, which is not what I want to do, I'm passing the interrupt number to the function...
Thanks in advance,
Jules
P.S. Now that I look at it your trying to see whats wrong with the stack frame, so i'll try and see what happens and i'll post as soon as I do the test...
Posted: Thu Jun 05, 2008 7:31 am
by Dex
I am not in C at all, but this is a commone C int stub
Code: Select all
_isr:
pusha
push es
push ds
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax,esp
push eax
mov eax, _int_handler
call eax
pop eax
pop gs
pop fs
pop ds
pop es
popa
add esp, 8
iret
I was only try to workout what's going wrong in the stack, but do not shoot the messenger.
Posted: Thu Jun 05, 2008 11:21 pm
by Candy
Code: Select all
_isr:
mov [store_1], eax
pop eax
mov [store_2], eax
mov eax, [store_1]
// pusha until popa
add esp, 4
sti
iret
Why do you do a pop eax, and then at the end add 4 to esp as well? That's going to mess up your stack.
Posted: Fri Jun 06, 2008 12:24 pm
by suthers
Thanks, I've managed to fix it.
@Candy: Thanks for the post, it allowed me to figure out what was wrong, I was still adding 4 to esp on top of pushing because I add stuff to the stack in the isr (as you probably figured out, that was the common part of the isr that... I was pushing a byte and for some reason adding 4, (Yah I'm pretty stupid sometimes...) so changing it to 1 fixed it.
Thanks,
Jules
edit: Oh and fixing this uncovered a series off other bugs...
Posted: Fri Jun 06, 2008 4:14 pm
by suthers
Oh and another weird thing, if I leave out -finline-functions in as an option, my isr works (Though now I suspect it doesn't return it to the right adress), but it produces loads of errors (probably because it doesn't return to the right address). But if I leave in, I still get the LDTR not valid error, anybody got an explanation for this?
Thanks in advance,
Jules
Posted: Fri Jun 06, 2008 5:44 pm
by Ryu
I noticed this besides whats already mentioned.
Code: Select all
_isr0:
cli
hlt <--- debugging???
push byte 0
push byte 0
jmp _isr
The most obvious thing you might want to check is the local descriptor table if it is utilised properly and that LDTR is properly set.
Posted: Fri Jun 06, 2008 8:39 pm
by kmcguire
suthers wrote:Thanks, I've managed to fix it.
@Candy: Thanks for the post, it allowed me to figure out what was wrong, I was still adding 4 to esp on top of pushing because I add stuff to the stack in the isr (as you probably figured out, that was the common part of the isr that... I was pushing a byte and for some reason adding 4, (Yah I'm pretty stupid sometimes...) so changing it to 1 fixed it.
Thanks,
Jules
edit: Oh and fixing this uncovered a series off other bugs...
I am still lost at how you were pushing a byte? You pushed sixty-four bits of data onto the stack inside the ISR stub as two zeros..
The
pop eax and
add esp, 4 looked correct. I can not find a instruction for pushing a immediate eight byte value in the 80386 instruction set while only incrementing the stack pointer by one. It increments it by four even though you only push one byte.