[SOLVED] Conversion exception

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

[SOLVED] Conversion exception

Post by HugeCode »

Hi all.

I have specific problem: somewhere in my code there's something that causes FPU exception when converting. It doesn't matter what am I converting or to what is it being converted, it just causes exception.

Code: Select all

math_abort: MSDOS compatibility FPU exception
Few examples of my conversions:

Code: Select all

;F2D
fld dword [esp]
push eax ;trash (esp+4)
fstp qword [esp]
;F2I
fld qword [esp]
pop eax
fistp dword [esp]
Whenever I try to do something with resulting value (for example when I compare it), another exception is thrown. I'm using bochs and I don't know how to debug which exception has been thrown, because exception doesn't stop execution. I think that raw content of stack is 0 (I tried to print it), but I'm not sure.

Does anybody have any idea what can cause such behaivor when converting? Is there any way for stopping it? I have read something about exception masking in control word, but converted value will be still incorrect, won't it?

Please help.
Last edited by HugeCode on Thu Jul 18, 2013 2:25 am, edited 1 time in total.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Conversion exception

Post by Combuster »

math_abort: MSDOS compatibility FPU exception
Unless you want all FPU errors routed over the PIC chip, start with fixing your processor control registers (it's in CR0 - forgot the bit's actual name).
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Conversion exception

Post by Brendan »

Hi,

The FPU has a "tag word" that says what is in each register. The default value for the tag word (e.g. after power up/reset) is 0x5555, which says "all registers contain a special value". If you try to load anything into an FPU register, you will get an "invalid operation; floating point register stack overflow" exception because the register is not marked as "empty" in the tag word.

The FPU also has a "control word". The default value of the control word (e.g. after power up/reset) is 0x0040; which says "precision exception masked, no other exceptions masked, single precision, round to nearest".

Before using the FPU you have to initialise the FPU. This includes doing a "fninit" instruction, which will set the tag word to 0xFFFF ("all registers are empty"); and should also include setting the control word (e.g. set it to something like "precision exception masked, denormal operand exception masked, underflow exception masked, no other exceptions masked, double extended precision, round to nearest").

In addition to that; Combuster is right - unless you have to deal with old CPUs (80386 or older, where the FPU isn't built into the CPU and therefore "native FPU exceptions" isn't supported); you should enable "native FPU exceptions" in CR0. If you don't do this, FPU exceptions get routed through the PIC chip to IRQ 13 (which is slow, ugly, has some race conditions, and doesn't work at all when there's multiple CPUs); and if you do enable "native FPU exceptions" then you get a normal exception (interrupt 16) instead.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
HugeCode
Member
Member
Posts: 112
Joined: Mon Dec 17, 2012 9:12 am

Re: Conversion exception

Post by HugeCode »

Thank you, with FINIT it works. I will have a look on that CR0 bit.
Post Reply