问题
I am trying to implement Newton - Raphson inversion algotihm in assembly according to this equation:
Xn+1 = Xn(2-b*Xn)
My function is:
.data
const:
.int 2
.text
.global inversion
inversion:
pushl %ebp
movl %esp, %ebp
fldl 8(%ebp) # load b
fldl 12(%ebp) # load X0
inv:
fst %st(2) # save Xn
fmul %st(1), %st(0) # b*Xn
fsubr const # 2-b*Xn
fmul %st(2), %st(0) # Xn(2-b*Xn)
fcomi %st(2), %st(0) # check if it the same result as before
jne inv # jump
# it should return the st(0)
leave
ret
And my C program:
#include <stdio.h>
extern float inversion (float a, float b);
int main(void)
{
float x = inversion (5,0.1);
printf ("%f\n", x);
return 0;
}
My problem is that this function doesn't return anything, and when I am debuggin it with gdb it shows that my function never stops, because values are never the same. In my opinion it's load bad numbers, it's what I am reading after loading data on stack (st(0), st(1), st(2)):
st0 2.6342588374767957140994886365053441e-314 (raw 0x3bed9ee6666680000000)
st1 5.2386907379892329317261356891322066e-11 (raw 0x3fdce6666a0500000000)
st2 2.6342588374767957140994886365053441e-314 (raw 0x3bed9ee6666680000000)
Thanks for all your responses.
回答1:
Yes, gdb
pointed you in the right direction: you are loading the arguments wrong. You used fldl
where the l
means double
when dealing with floating point instructions. I guess you thought the l
meant 4 bytes
. To load 4 byte floats you need the flds
instruction.
Furthermore, fsubr
expects a floating point number but you give it an integer. Solution: change .int 2
to .float 2
. Also change to fsubrs
for safety (although that is the default).
Finally, you are leaving 3 values on the fpu stack, which is not according to the expected calling convention and can cause problems later. You should only leave the return value there.
来源:https://stackoverflow.com/questions/23501773/newton-raphson-inversion-algorithm-in-assembly