Solved

Linux nasm square root algorithm poblem

Posted on 2004-04-07
5
515 Views
Last Modified: 2008-02-01
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
0
Comment
Question by:SaumZ
  • 3
  • 2
5 Comments
 
LVL 6

Expert Comment

by:joghurt
ID: 10784584
I believe you have a reason for not using FSQRT instead.

Well, by definition "jl" jumps if "SF <> OF".
However, fcomi sets the following flags: ZF, PF, CF.
So change jl to jc. Voila.
0
 

Author Comment

by:SaumZ
ID: 10784909
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.
0
 
LVL 6

Expert Comment

by:joghurt
ID: 10786189
"jnc", sorry.
0
 
LVL 6

Accepted Solution

by:
joghurt earned 250 total points
ID: 10786259
Well, another approach. There were too many finit's even for the first sight so I've tried to reorganize the things a bit.

.L1:
fld         qword ptr [x_new]
fstp        qword ptr [x_old]
fld         qword ptr [x]
fdiv        qword ptr [x_old]
fadd        qword ptr [x_old]
fdiv        qword ptr [x2]
fstp        qword ptr [x_new]
fld         qword ptr [x_old]
fsub        qword ptr [x_new]
fabs
fdiv        qword ptr [x_new]
fcomp       qword ptr [epsilon]
fnstsw      ax  
test        ah,41h
je          .L1

I haven't used fcomi because it won't run on older machines. (And because my development environment couldn't compile P6 instructions. :-)
But you can give it a try.
0
 

Author Comment

by:SaumZ
ID: 10810023
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.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

In this step by step tutorial with screenshots, we will show you HOW TO: Enable SSH Remote Access on a VMware vSphere Hypervisor 6.5 (ESXi 6.5). This is important if you need to enable SSH remote access for additional troubleshooting of the ESXi hos…
A procedure for exporting installed hotfix details of remote computers using powershell
This video discusses moving either the default database or any database to a new volume.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now