Calling assembly functions from C

note, Jun 17, 2024, on Mitja Felicijan's blog

This is using the portable GNU assembler and TinyCC compiler but GCC or Clang can be used as well.

First lets define a simple function in assembly.

# sum.s
.intel_syntax noprefix

.global sum

.text

sum:
    add rdi, rsi
    mov rax, rdi
    ret

Lets compile this with GNU assembler as sum.s -o sum.o.

Now we need a C program that calls this function.

// main.c
#include <stdio.h>

// We need to define the signature of the function.
int sum(int a, int b);

int main() {
    for(int i=0; i<10; ++i) {
        printf("SUM of 5+%d is %d\n", i, sum(5, i));
    }
    return 0;
}

Now lets compile and link into final program with tcc main.c sum.o -o main.

Use this table to see what each register is being used for.

RegisterConventional useLow 32-bitsLow 16-bitsLow 8-bits
%raxReturn value, caller-saved%eax%ax%al
%rdi1st argument, caller-saved%edi%di%dil
%rsi2nd argument, caller-saved%esi%si%sil
%rdx3rd argument, caller-saved%edx%dx%dl
%rcx4th argument, caller-saved%ecx%cx%cl
%r85th argument, caller-saved%r8d%r8w%r8b
%r96th argument, caller-saved%r9d%r9w%r9b
%r10Scratch/temporary, caller-saved%r10d%r10w%r10b
%r11Scratch/temporary, caller-saved%r11d%r11w%r11b
%rspStack pointer, callee-saved%esp%sp%spl
%rbxLocal variable, callee-saved%ebx%bx%bl
%rbpLocal variable, callee-saved%ebp%bp%bpl
%r12Local variable, callee-saved%r12d%r12w%r12b
%r13Local variable, callee-saved%r13d%r13w%r13b
%r14Local variable, callee-saved%r14d%r14w%r14b
%r15Local variable, callee-saved%r15d%r15w%r15b
%ripInstruction pointer
%rflagsStatus/condition code bits

You can read more about x86-64 Machine-Level Programming.



Other notes