Reputation: 11
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
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