SaumZ
asked on
Linux nasm square root algorithm poblem
I am programming with the FPU under linux and the NASM assembler and linking using gcc
Here is the algorithm I am implementing:
take in x from the keyboard
Initialize x_new = x
do
x_old = x_new;
x_new = (x_old + x / x_old) / 2;
while |x_old - x_new|/x_new > e
I am having the problem with my compare and my conditional jump.
I have tested the values of the algorthm throughout and the values are correct to what I worked out on paper.
;------------------------- ---------- ---------- ---------- ---------- ---------- ---
extern printf
extern scanf
global main
segment .data
prompt: db "Please enter a number: ",0
format: db "%lf", 0
output: db "%lf",10, 0
epsilon dq 0.0001
x2: dq 2.0
segment .bss
x: resq 1
x_new: resq 1
x_old: resq 1
x_temp: resq 1
segment .text
main:
pusha
push prompt
call printf
add esp, 4
push x
push format
call scanf
add esp, 8
fld qword [x] ;fstack: x
fstp qword [x_new] ;fstack:
;x_new = x
.L1: finit
fld qword [x_new] ;fstack: x_new
fstp qword [x_old] ;fstack:
;x_old = x_new
finit ;clear the stack
;now lets make x_new = (x_old + (x/x_old))/2
fld qword [x] ;fstack: x
fdivr qword [x_old] ;fstack: x/x_old
fadd qword [x_old] ;fstack:(x_old + (x/x_old))
fdiv qword [x2] ;fstack:(x_old + (x/x_old))/2
fstp qword [x_new] ;fstack:
finit ;clear the stack
;now lets make |x_old - x_new|/x_new
fld qword [x_old] ;fstack: x_old
fsub qword [x_new] ;fstack: x_old - x_new
fabs ;fstack: |x_old - x_new|
fdiv qword [x_new] ;fstack: |x_old - x_new|/x_new
fld qword [epsilon] ;fstack: epsilon, |x_old - x_new|/x_new
;PROBLEM IS WITH THE COMPARE AND JUMP HERE
fcomi st1 ;compare ST0 with ST1
jl .L1
finit
push dword [x_new + 4] ;outputting x_new after loop
push dword [x_new]
push output
call printf
add esp, 12
popa
mov eax, 0
ret
Here is the algorithm I am implementing:
take in x from the keyboard
Initialize x_new = x
do
x_old = x_new;
x_new = (x_old + x / x_old) / 2;
while |x_old - x_new|/x_new > e
I am having the problem with my compare and my conditional jump.
I have tested the values of the algorthm throughout and the values are correct to what I worked out on paper.
;-------------------------
extern printf
extern scanf
global main
segment .data
prompt: db "Please enter a number: ",0
format: db "%lf", 0
output: db "%lf",10, 0
epsilon dq 0.0001
x2: dq 2.0
segment .bss
x: resq 1
x_new: resq 1
x_old: resq 1
x_temp: resq 1
segment .text
main:
pusha
push prompt
call printf
add esp, 4
push x
push format
call scanf
add esp, 8
fld qword [x] ;fstack: x
fstp qword [x_new] ;fstack:
;x_new = x
.L1: finit
fld qword [x_new] ;fstack: x_new
fstp qword [x_old] ;fstack:
;x_old = x_new
finit ;clear the stack
;now lets make x_new = (x_old + (x/x_old))/2
fld qword [x] ;fstack: x
fdivr qword [x_old] ;fstack: x/x_old
fadd qword [x_old] ;fstack:(x_old + (x/x_old))
fdiv qword [x2] ;fstack:(x_old + (x/x_old))/2
fstp qword [x_new] ;fstack:
finit ;clear the stack
;now lets make |x_old - x_new|/x_new
fld qword [x_old] ;fstack: x_old
fsub qword [x_new] ;fstack: x_old - x_new
fabs ;fstack: |x_old - x_new|
fdiv qword [x_new] ;fstack: |x_old - x_new|/x_new
fld qword [epsilon] ;fstack: epsilon, |x_old - x_new|/x_new
;PROBLEM IS WITH THE COMPARE AND JUMP HERE
fcomi st1 ;compare ST0 with ST1
jl .L1
finit
push dword [x_new + 4] ;outputting x_new after loop
push dword [x_new]
push output
call printf
add esp, 12
popa
mov eax, 0
ret
ASKER
I tried the jump with jc, and my code is still only doing one iteration. and outputting for example:
Please enter a number: 20
10.500000
This number is correct, but only after one iteration.
this is the output that is at the bottom. of my code, where it outputs x_new
I also tested the number that I have from |x_old - x_new|/x_new
by putting it in a temp variable and outputting it and comparing to what I calculated using pencil and paper, and that is correct also.
Maybe the problem lies somewhere else? I am not sure at this point.
The reason for not just using fsqrt is that I am just learning the fpu programming, and I am trying to get myself used to programming in it by using different instructions with it.
So, I may have logic errors someplace else in my code, but to me, it all looks correct.
Please enter a number: 20
10.500000
This number is correct, but only after one iteration.
this is the output that is at the bottom. of my code, where it outputs x_new
I also tested the number that I have from |x_old - x_new|/x_new
by putting it in a temp variable and outputting it and comparing to what I calculated using pencil and paper, and that is correct also.
Maybe the problem lies somewhere else? I am not sure at this point.
The reason for not just using fsqrt is that I am just learning the fpu programming, and I am trying to get myself used to programming in it by using different instructions with it.
So, I may have logic errors someplace else in my code, but to me, it all looks correct.
"jnc", sorry.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
My whole problem in the task was a fdivr in place of a fdiv in my origional code...
I will give you the points, thank you for your help.
I will give you the points, thank you for your help.
Well, by definition "jl" jumps if "SF <> OF".
However, fcomi sets the following flags: ZF, PF, CF.
So change jl to jc. Voila.