Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions

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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Convert MP3/Wav to bin format ? 4 949
writing Bios 6 449
Get register length/size? 5 608
File Not Found Exception 12 113
In this article we will learn how to fix  “Cannot install SQL Server 2014 Service Pack 2: Unable to install windows installer msi file” error ?
This article explains the steps required to use the default Photos screensaver to display branding/corporate images
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

861 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