2
votes

Hello I am trying to learn assembly and learn how to work with floating point numbers in x86_64. From what I understand arguments are passed in xmm0, xmm1, xmm2, and so on, and the result is returned in xmm0. So I am trying to make a simple assembly function that adds to double together. Here is the function

.text

.global floatadd
.type floatadd,@function

floatadd:
    addsd %xmm1,%xmm0
    ret

And here is the C code I am using as well.

#include<stdio.h>

int main(){
    double a = 1.5;
    double b = 1.2;
    double c = floatadd(a,b);
    printf("result = %f\n",c);
}

I have been trying to following what is happening in gdb. When I set a breakpoint in my function I can see xmm0 has 1.5 and xmm1 has 1.2 and when they are added together they 2.7. In gdb print $xmm0 gives v2_double = {2.7000000000000002, 0} However when my function returns from main and calls

cvtsi2sd %eax,%xmm0 

Print $xmm0 becomes v2_double = {2, 0}. I am not sure why gcc calls that or why it is uses the 32bit register instead of the 64bit register. I have tried using the modifier %lf, and %f and both of them do the same thing.

What is happening?

1
Where's the prototype for floatadd? If you're not specifying one, your compiler is treating floatadd as returning int, which would explain the use of that instruction.Peter Huene

1 Answers

3
votes

The problem is that you failed to declare floatadd before calling it. So the compiler assumes it returns an int in %eax and converts that int to a double. Add the declaration:

double floatadd(double, double);

before main.

Using -Wall or whatever equivalent your compiler uses to enable warnings would probably have told you about this problem...