You seem to have a lot of unneeded stack operations in your code, however, there is a more sinister problem here, storing the fp result in a DWORD will truncate it, so there is no point in round it unless you plan on round to the nearest integer value (which is what your second attempt does).
Up vote 1 down vote favorite share g+ share fb share tw.
I'm currently trying to get an average as a floating point number, rounded to the nearest .001 Being pretty new to floating point instructions and such, this is what I have so far from the reading and searching that I've done. Sum: a DWORD holding the value 90 (sum of acc number of items) acc: a DWORD holding the value 7 (number of items) res: a DWORD to hold the answer. In the end, edx has the value 0.
Why is this? Additionally, how do I round floating point? Or...is there a better way to do this?
My asm: push dword ptr sum fild dword ptr esp push dword ptr acc fild dword ptr esp add esp,4 fdiv st(0), st(1) sub esp,4 fstp dword ptr esp pop eax add esp,4 mov edx, eax Also, I tried this: finit fild sum fidiv acc frndint fist res mov eax, res But...this results in: 2147483648 (DWORD range) assembly x86 floating-point link|improve this question edited Feb 9 at 8:22 asked Feb 9 at 6:02Dacto362523 79% accept rate.
You seem to have a lot of unneeded stack operations in your code, however, there is a more sinister problem here, storing the fp result in a DWORD will truncate it, so there is no point in round it unless you plan on round to the nearest integer value (which is what your second attempt does). As such I'll base an example off your second attempt: PUSH ECX FILD ESP PUSH EDX FILD ESP FDIV FRNDINT ADD ESP,4 FISTP DWORD PTR ESP POP EAX RETN this function assumes the value in ECX, the count in EDX and returns a rounded average in EAX. For here you can just change it to use your globals, or call it as a function using your globals.
I replaced the ecx/edx with sum/acc and at the end eax still returns the DWORD range of 2147483648. :/ – Dacto Feb 9 at 7:45 @Dacto: then there is something wrong on your end, as this works find for me (returning the expected 13, using your inputs). Try running through it in a debugger – Necrolis Feb 9 at 7:50 Thank you.
Debugger worked it out. Foolish problem. Much appreciated.
– Dacto Feb 9 at 7:54 Rounding to 0.001 isn't a very good idea, because this is an infinite periodic fraction in binary. – drhirsch Feb 9 at 8:14 I know...but I need to stop some where ;) but also trying to learn how to round to a specific place in general with floating point. – Dacto Feb 9 at 8:20.
I am not sure I understand your question correctly, but at least the 2nd bit of code seems valid. Whether it does what you want is another question. It does this: finit fild sum ;//ST(0) = 90 fidiv acc ;//ST(0) = ST(0) / acc = 90 / 7 = 12.857.. frndint ;//ST(0) = 13 fist res ;//RES= ST(0) = 13 mov eax, res ;//EAX = RES = 13 In other words, you are calculating round(90/7) = 13.
Now, this is a straightforward division, not an average. You'd obviously calculate an average by summing over N items and then dividing by the number of items. The second thing is that you are working with integers, not with floating point values: the fIld, fIdiv and fIst instructions work are designed to work with integer, not floating point values.
If you store a value from the FPU into memory with fIst rather than fst/fstp this value in memory will be an integer value, not a floating point value. Is it this you want? To store a floating point value from the FPU to memory pointed to by eax, you can use fstp dword ptr eax ;// Store Single-Precision Floating point value (4 bytes) fstp qword ptr eax ;// Store Double-Precision Floating point value (8 bytes) fstp tbyte ptr eax ;// Store Long Double-Precision Floating point value (10 bytes) The Single and Double stores (but not the tbyte ptr) also work with fst instead of fstp.
Yes this is exactly what I want it to do (preferably I'd like to round to the nearest .001 - understanding that I would be using fst/fstp for that). However, regardless, res/eax still result in 2147483648 – Dacto Feb 9 at 7:48 @Dacto - I cannot confirm your result. When I ran the code, I had the value of 13 in EAX – PhiS Feb 9 at 7:54 I figured it out and get 13 also now :.
How would I go about rounding to the nearest .001? I changed the fIxx to fld, fdiv, and fstp, but now I get the value of 1108502118 in eax – Dacto Feb 9 at 8:13 @Dacto - there's no single instruction that just rounds to an arbitrary precision for you; you have to write the code for that yourself. If you have trouble, I think it would be easiest if you ask this in a separate question.
– PhiS Feb 9 at 8:55.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.