Linux nasm square root algorithm poblem

Posted on 2004-04-07
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
     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
        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
        fcomi st1                       ;compare ST0 with ST1
        jl .L1
        push dword [x_new + 4]   ;outputting x_new after loop
        push dword [x_new]
        push output
        call printf
        add esp, 12

        mov eax, 0
Question by:SaumZ
  • 3
  • 2

Expert Comment

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.

Author Comment

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

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.

Expert Comment

ID: 10786189
"jnc", sorry.

Accepted Solution

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.

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]
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.

Author Comment

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.

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity Code Gerators 3 488
Windows 7, Delphi Code, Drawcolumn ERROR 13 408
Get register length/size? 5 604
Problem with Filesystemobject or .NET version 3 58
There’s a good reason for why it’s called a homepage – it closely resembles that of a physical house and the only real difference is that it’s online. Your website’s homepage is where people come to visit you. It’s the family room of your website wh…
In this increasingly digital world, security hacks are no longer just a threat, but a reality. As we've witnessed with Target's big identity hack 2013, Heartbleed in 2015, and now Cloudbleed, companies and their leaders need to prepare for the unthi…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
Established in 1997, Technology Architects has become one of the most reputable technology solutions companies in the country. TA have been providing businesses with cost effective state-of-the-art solutions and unparalleled service that is designed…

832 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