Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


fxch always sets register to NaN

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Tue Sep 27, 2016 1:47 pm    Post subject: fxch always sets register to NaN Reply with quote

I'm trying to use the fxch command to swap floats to the top of the FPU stack, but whenever I do, st(0) is set to NaN. The register that I'm swapping it with starts out with a legitimate floating point number, but seems to be getting corrupted by the fxch function.

Is it supposed to do that? Is there a way I can stop it?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4711

PostPosted: Tue Sep 27, 2016 3:09 pm    Post subject: Reply with quote

Post your code. Whichever of the floating point registers you're swapping st(0) with obviously contains a NaN value. Set a breakpoint on the fxch instruction and look at the FPU registers to see.
_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
CodeReaver
Newbie cheater
Reputation: 0

Joined: 19 Apr 2005
Posts: 24

PostPosted: Tue Sep 27, 2016 9:32 pm    Post subject: Reply with quote

Code:
003D0107 - DB 05 084DC500        - fild dword ptr [00C54D08] { [00000038] }
003D010D - D9CA                  - fxch st(2)
003D010F - 83 EC 08              - sub esp,08 { 8 }
003D0112 - D9 5C 24 FC           - fstp dword ptr [esp-04]
003D0116 - D9 1C 24              - fstp dword ptr [esp]
003D0119 - D9 05 08003D00        - fld dword ptr [003D0008] { [0.80] }
003D011F - D9 05 0C003D00        - fld dword ptr [003D000C] { [1.00] }
003D0125 - 66 9C                 - pushf
003D0127 - 50                    - push eax
003D0128 - D8D1                  - fcom st(0),st(1)
003D012A - DFE0                  - fnstsw ax
003D012C - 9E                    - sahf
003D012D - 72 02                 - jb 003D0131
003D012F - D9C9                  - fxch st(1)
003D0131 - DCCA                  - fmul st(2),st(0)
003D0133 - 58                    - pop eax
003D0134 - 66 9D                 - popf
003D0136 - DDD8                  - fstp st(0)
003D0138 - DDD8                  - fstp st(0)
003D013A - D9 04 24              - fld dword ptr [esp]
003D013D - D9 44 24 FC           - fld dword ptr [esp-04]
003D0141 - 83 C4 08              - add esp,08 { 8 }
003D0144 - D9CA                  - fxch st(2)
003D0146 - C3                    - ret


I didn't have the code with me at work, however given that the register is correct until after the second line and wrong from then onward, I didn't think it would be necessary.

These are the extended FPU registers before 003D010D (fxch st(2))
56.00
Nan
8048628.00
1026.00
632.00
1026.00
632.00
1026.00

These are the extended FPU registers afterwards
Nan
Nan
56.00
1026.00
632.00
1026.00
632.00
1026.00

So, by your logic, 8048628.00 is obviously not a number.

It puts NaN in st(0) whichever register I exchange it with. For example, I expect to see if I change it to fxch st(3)
1026.00
Nan
8048628.00
56.00
632.00
1026.00
632.00
1026.00

But I just end up with this
Nan
Nan
8048628.00
56.00
632.00
1026.00
632.00
1026.00
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4711

PostPosted: Tue Sep 27, 2016 11:16 pm    Post subject: Reply with quote

This isn't a common problem to see, so I wouldn't put it past some people to accidentally do something stupid like use a register they didn't mean to.

The only reason I can find after taking a brief look through the documentation is that the tag of the register st(2) is marked as empty, causing the fxch instruction to substitute it for a QNaN prior to the exchange.

To confirm this, pop st(0) and st(1), execute an FXAM instruction, and check the FPU status word (FNSTSW) to see if st(2) is empty or not. Another more explicit way would be to use FNSTENV to get the FPU tag word. The order of the FPU tag word corresponds to the physical registers, so get which register is the top of the stack from the FPU status word (should already have it via FNSTENV) in order to figure out which physical register is st(2).

If st(2) is marked as empty (which means that register technically isn't a number Razz), store the FPU environment, clear that tag's bits, load the FPU environment (FLDENV), and check if it works then.

See Intel's Software Developer's Manual Volume 1 Chapter 8 for more detailed information.

An easier solution might be to simply choose a different injection point and/or backtrace to where the program uses the value of st(2) and hook there.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites