NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: andyz74 on January 29, 2025, 09:35:26 PM
-
Hello all of you,
I am sure, this is a absolutely stupid failure of mine, but I don' get it... so, please have a look and see, if you are able to find the problem
get_wu:
mov rbx, qword [para_w] ; load my value to rbx to ensure I can see in debugger if it is right
movsd xmm1, qword [para_w] ; get my value to xmm1
sqrtsd xmm0, xmm1 ; take root of xmm1 and save it to xmm0
cvttsd2si rbx, xmm0 ; convert (and truncate) xmm0 to integer and store it in rbx
inc rbx
ret
in the debugger I see, that rbx and xmm1 are correct loaded with my value,
after the sqrtsd , I see "something" in xmm0, which I assume it is my packed calculated root
and after the cvttsd2si, I have always 0 (zero) in my rbx. not a correct calculated root.
Please, what am I doing wrong?
Note: I do not need the correct root, but the integer part has to be correct. (sqrt(10) => 3) is good for me
-
First of all: What do you want to do?
-
I'll assume you just want to extract the square root of an integer value and get an integer result using `sqrtsd` instruction...
First: double type has 53 bits of precision and 11 bits in the expoent of the scale factor plus the signal bit. This means a double is 64 bits long (but with less precision than an long long int)... Let's say your function is defined to obey SysV ABI for x86-64 (not for Windows):
; unsigned long long int sqrtroot( unsigned long long int x );
; Entry: RDI = x
; Exit: RAX
global sqrtroot
align 4
sqrtroot:
cvtsi2sd xmm0,rdi ; Convert RDI to double scalar in XMM0.
sqrtsd xmm0,xmm0 ; xmm0 = sqrt(xmm0)
cvtsd2si rax,xmm0 ; Convert XMM0 double scalar to RAX (this convertion applies rounding).
ret
For Windows change RDI to RCX.
If you want to use unsigned int, instead, you need to zero the upper 32 bits of RDI:
; unsigned int sqrtroot( unsigned int x );
; Entry: EDI = x
; Exit: EAX
global sqrtroot
align 4
sqrtroot:
mov edi,edi
cvtsi2sd xmm0,rdi ; Convert RDI to double scalar in XMM0.
sqrtsd xmm0,xmm0 ; xmm0 = sqrt(xmm0)
cvtsd2si rax,xmm0 ; Convert XMM0 double scalar to RAX (this convertion applies rounding).
ret
PS: GCC makes sure the upper double from xmm0 is zero beginning with pxor xmm0,xmm0, but we don't need to do this since we're dealing only with an scalar...
-
This works great! Many thanks, Frederico!
For learning purposes I try to make programs to find primes. And to reduce calculation times I will divide the actual number through a cycle from [sqrt(actual number)] downto 3. (I test only the odd ones...)
Therefor I need to calculate the squareroots.
Many thanks, I've learned just a little bit. :-)
-
A note of caution... If you intend to calculate the square root of an unsigned long long int, the double precision has only 53 bits of precision (while unsigned long long int has 64)... So the first example is insufficient: You need a bigger floating point precision that is not available to SSE... You must use fp87 instead:
; Input: RDI = x
; Output RAX = sqrt(x)
squareroot:
fild qword [rsp-8],rdi ; using red zone here.
fsqrt
fistp qword [rsp-8]
mov rax,[rsp-8]
ret
-
I have another version of my program, in which I use the fp87 for getting the squareroot. I test both.
The huge amount of divisions to see, what is prime and what not, is in the moment done by normal DIV command. But later, I will try to do this with fp87, and a third version to do it with sse2.
-
I have another version of my program, in which I use the fp87 for getting the squareroot. I test both.
The huge amount of divisions to see, what is prime and what not, is in the moment done by normal DIV command. But later, I will try to do this with fp87, and a third version to do it with sse2.
You don't need floating point or square root... Here:
_Bool isprime( unsigned int n )
{
unsigned int d;
unsigned long long int f;
if ( n <= 3 )
return n >= 2;
d = n % 6;
if ( d != 1 && d != 5 )
return 0;
for ( f = 5; f * f <= n; f += 2 )
if ( ( n % f ) == 0 )
return 0;
return 1;
}
-
Main topic for me is learning Assembler a bit. :-)
Good night now, in Germany we habe 10 pm, time to sleep.