I am getting acquainted to making C/C++ talk to ASM functions. For this, I started by understanding how the registers are used for arguments.
I have 2 routines that will just multiply 2 64bit floats. One of them returns the result, the other one saves the result in the first argument, that is being passed by reference. The first case was easy enough and it worked without issues, but the second case I couldn't make it work until I made g++ generate the assembly code to see how it should be done. The assembly and c++ host code go in their own files:
section .text
global Mul_Double_ASM
global Mul_Double_ASM_2
Mul_Double_ASM:
mulsd xmm0, xmm1
ret
Mul_Double_ASM_2:
mulsd xmm0, [rdi]
movsd [rdi], xmm0
The C++ code is simply:
#include <iostream>
using namespace std;
extern "C" double Mul_Double_ASM(double val1, double val2);
extern "C" void Mul_Double_ASM_2(double &val1, double val2);
int main(void)
{
double val_1,
val_2;
cin >> val_1;
cin >> val_2;
cout << std::fixed << Mul_Double_ASM(val_1, val_2) << endl;
Mul_Double_ASM_2(val_1, val_2);
cout << std::fixed << val_1 << endl;
return 0;
}
It reads 2 user-provided numbers and multiply them with the assembly functions. Both codes work now, but the way I was attempting Mul_Double_ASM_2 was:
mulsd xmm0, xmm1
No ret at the end, and when I printed the value of val_1 it had the original value. Then I learned that the first argument is stored in the register rdi and so made the adjustment on my code.
So my question is: I could multiply xmm0 and xmm1 directly in the first function and never used rdi, but when the function is pass-by-reference then I needed to use rdi. Can you explain why using xmm0 and xmm1 works in the first case and not in the second?