2
votes

I'm trying to make a program in C that uses a function from Assembly. Below you can see the code:

sum_c.c

#include <stdio.h>

extern int _assemblySum(int x, int y);

int main(int argc, char *argv[]){
    int total;

    total = _assemblySum(4, 2);
    printf("%d\n", total);
    return 0;
}

assembly_Sum.asm

SECTION .DATA

SECTION .TEXT
    GLOBAL _assemblySum

_assemblySum:
    push rbp
    mov rbp, rsp
    mov rax, [rbp+16]
    mov rbx, [rbp+24]
    add rax, rbx
    pop rbp
    ret

COMPILE

nasm -f elf64 assembly_sum.asm -o assembly_sum.o
gcc c_sum.c assembly_sum.o -o sum
./sum

When I run the program I just get random numbers like -1214984584 or 2046906200. I know that I need to use the registers rdi, rsi, rdx and rcx because the 64bit GNU/Linux compiler uses them (Passing arguments from C to 64bit linux Assembly). But how can I do that?

1
mov RDI to RAX and then add RSI to RAX (leaving result in RAX)? A more elegant way might to do the add via the LEA instruction. For example this function would do it _assemblySum: lea rax, [rdi+rsi] ret . LEA is generally used to compute a memory address, but it can add two registers storing it in a 3rd. This effectively adds RSI+RDI and stores it in RAX. - Michael Petch
In your case parameter 1 is in RDI, parameter 2 is in RSI per the System V 64-bit calling convention. - Michael Petch
@MichaelPetch Thanks, work perfectly. - Thulio Amorim

1 Answers

1
votes

You may have confused which calling convention is being used.

Linux uses the 64-bit System V calling convention. Under this convention, registers are strongly preferred over the stack for the passing of INTEGER type parameters. The registers for integer passing are used in the following order:

  • %rdi
  • %rsi
  • %rdx
  • %rcx
  • %r8
  • %r9

If additional Integer parameters are used, they will be passed on the stack.

You can find detailed information in the System V ABI specification.