1
votes

I am implementing a C defined function in assembler. The function is as follows

extern void swapNums(float* one,float* two,float* three);

A) swapNums accepts 3 references to a float, and then places the smallest of these 3 values in 'one', the middle value in 'two' and the largest of the three values in 'three'.

I want to know:

  1. Which registers are used to store the references to the 3 floats, i.e. Is it rsi,rdi,rdx... or is it xmm0,xmm1,xmm3 ...

  2. How do I change the value in *one, *two, *three so that i can satisfy A)

I am accustomed to implementing C functions in assembler when the parameters of the function are passed by value. For example when dealing with floating point parameters, I follow the conventions below:

section .data

    global <name of function>

<name of function>:
    movss [x1], xmm0 ; move the first parameter into memory location x1
    movss [x2], xmm1 ; move the second parameter into memory location x2
    movss [xNorm], xmm2 ; move the third parameter into memory location x3

and then link the object files of the .asm and .c files when creating an executable

2
Pointers are passed by value (so just push pointer value onto the stack), you just need to access the variable through indirection from the pointer inside the function body, - Jean-Baptiste Yunès
Those are pointers, not references, AFAIK. I think would involve fetching the value at the address contained in the pointer. I am not an x86 assembly expert, though. edit: @Jean-BaptisteYunès, you beat me :) - MayeulC
What operating system? Windows and UNIX have different ABIs. - fuz
You can also "cheat" a bit, write a function in C like float testAbi(float *one) { return *one; } and compile it with assembly listing to see how C would work with that pointer. - Ped7g
@Jean-BaptisteYunès: Both major x86-64 ABIs pass args in regs, not the stack. But yes, a pointer arg is just a value, passed the same way as an equal-sized integer. See the x86 tag wiki for links to ABI docs that specify what goes where. Or just look at where a compiler targeting that ABI puts things. - Peter Cordes

2 Answers

3
votes

I've got the exact same problem, and I figured it out.

rdi contains the literal address, [rdi] will 'point' to the value stored at that address; so the three addresses will be stored at rdi, rsi, and rdx (Linux, and Mac OS/X); or rcx, rdx, and r8 (Windows).

So then to move the actual values that need to be compared across to the SSE registers you need to use, movss xmm0, [rdi].

Finally to get the floats back across to the C program, you need to use movss [rdi], xmm0: this will move the value of xmm0 over to where rdi is 'pointing' to.

2
votes

There is no pass by reference in C because there are no references in C. When programming in C don't use the word "reference", forget that it even exists. All values in C are passed by value because they are values, not references which don't exist. Pointers are values, if that wasn't clear. (Strictly speaking, the value of a pointer is a reference to another object so we can't completely forget the word "reference", but that really confuses people when learning C).

When writing x86_64 (your question implies x86_64, not x86 which your title mentions) assembler all pointers are handled exactly the same regardless of the type they point to and in the function call ABI they are passed in the same registers as integer values.