Tix Issence
Tix Issence

Reputation: 11

x86 Assembly (NASM) How to nth root or raise floating point value with fraction

I have an upcoming project next week and I have been spending the last 2 days figuring out how to do an nth root.

I need to Simulate Geometric Mean in Assembly NASM.

I know FPU has an instruction for Square Rooting but that won't really take me far.

Currently, I can input as many inputs as I want and it multiplies them with no problem. But I get stuck with the 'nth root' part as I do not know how to do it with NASM.

This is my current code:

    global _main
    extern _printf, _scanf, _system

    section .text

    _main:
    mov ebp, esp; for correct debugging
push clr
call _system
add esp, 4

    ; start of INITIALIZE
    ;printf("Enter number of elements")
push print1
call _printf
add esp, 4
    ; scanf number of elements
push n
push scan1
call _scanf
add esp, 8

   ; printf("enter n integers")
   push dword [n]
push print2
call _printf
add esp, 8

   fld qword [n2]


   ; scan first element
   push n2
   push scan2
   call _scanf
   add esp, 8

   fld qword [n2]

   JE J1

   MOV EBX, 1

   CMP EBX, [n]
   JE J1

   L1:

   push n2
   push scan2
   call _scanf 
   add esp, 8

   fld qword [n2]
   fmul st1, st0
   fstp qword [ans]

   INC EBX
   CMP EBX, dword [n]
   JE J1
   LOOP L1

   J1:

   fst qword [ans]

   push dword [ans+4]
   push dword [ans]
   push print3
   call _printf
  add  esp, 12

   mov dword [data8], n

   fld qword [data7]
   fld qword [data8]

   fdiv st1, st0

   fstp qword [ans]


   fst qword [ans]

   push dword [ans+4]
   push dword [ans]
   push print3
   call _printf
  add  esp, 12

   xor eax, eax
   ret

   section .data
   clr      db "cls", 0
   print1   db "Enter the number of elements:", 13,10,0
   scan1    db "%d" , 0
   scan2    db "%lf" , 0
   n        dd 0
   n2       dq 0.0
   n3       dq 0.0
   print2   db "Enter %d values:", 13,10,0
   print3   db "Value is %g", 13, 10,0
   data8    dq 3.0
   ans      dq 0.0
   loopstart dq 1.0
   data7    dq 1.0

Or is it also possible to use an external C function for extracting an nth root?

EDIT: Trying to use the _pow from C. I have this code but it isn't working can someone help?

       LEA ESI, [return]

       push ESI
       push dword [pushingthing+4]
       push dword [pushingthing]
       push dword [ans+4]
       push dword [ans]
       push pow1
       call _pow
       add  esp, 24

       section   .data

       return   dq 0.0
       pushingthing dq 2.0
       pow1     dd "%g, %g", 13, 10, 0

Doing this because pow (in C) has a format of pow(x,y) which are both double and returns a double value. Please check.

Upvotes: 0

Views: 932

Answers (1)

Jester
Jester

Reputation: 58762

Using push to pass arguments, especially doubles, will make your head hurt with all the reversing and halving :) You should just allocate space and use the appropriate mov instructions. You still didn't say what environment you are in, but most of them return result in st(0) (ie. floating point stack). As such, an example could be:

sub esp, 16          ; space for 2 doubles
fld qword [x]        ; load 1st arg
fstp qword [esp]     ; write to stack
fld qword [y]        ; load 2nd arg
fstp qword [esp+8]   ; write to stack
call _pow
; result is now in st(0) print it
mov dword [esp], fmt ; format string
fstp qword [esp+4]   ; pass result as arg
call _printf
add esp, 16          ; free stack space

x: dq 16.0
y: dq 0.25
fmt: db "%g", 13, 10, 0

Upvotes: 4

Related Questions