1

I have problems with linking c and assembly code. Tried to search some solutions, but none of which I found worked for me.

c file "l3.c" looks like this:

#include <stdio.h>
#include <stdlib.h>

const int INP_SIZE = 100;

extern int mult(int c1, int c2);

int main()
{
    char number[INP_SIZE];

    scanf("%s",number);
    printf("You typed: %s \n",number);

    int j=2;
    int k=5;
    j = mult(j,k); #here is the problem
    printf("%d",j);

    scanf("%s",number);
    return 0;
}

and asembly "mult.s" like this:

.type mult, @function
mult:
push %rbp
mov %rsp, %rbp
mov 8(%rbp), %rbx
mov 12(%rbp), %rcx

mov $0, %rax
add %rbx, %rax;
add %rcx, %rax;

mov %rbp, %rsp
pop %rbp
ret

In my makefile i got following lines(most recent solution i googled):

l3:
    as -g -o mult.o mult.s
    gcc -o l3.o -c l3.c
    gcc l3.o mult.o

When I type make in console it is throwing: undefined reference to 'mult' when I comment //j = mult(j,k); program works fine. How should I link this?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
Kmaczek
  • 638
  • 2
  • 8
  • 23

1 Answers1

3

It looks like you're not exporting mult as a symbol, so the linker can't find it later on. How to do it correctly depends on what assembler you're using. Since you're using AT&T syntax, I'm going to guess GNU as - in that case just add .global mult at the top of your assembly file.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • Good to hear it helped. It's a bit weird that your function is called `mult`, but just appears to add two values from the stack. How do they get there? – Carl Norum May 19 '13 at 16:10
  • Yes, it should be called sth like add. There is long and not interesting story behind this... You mean how this values get there? Heh, I'm just trying to figure out how to get in assembly, arguments that I passed in c. – Kmaczek May 19 '13 at 17:07
  • 1
    Gotcha. For 64-bit intel, it's probably easier than you're making it, based on what I see in this example. Check out this link: http://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions – Carl Norum May 19 '13 at 17:14
  • I've just read other article. "the first six parameters go into rdi, rsi, rdx, rcx, r8, and r9." ugh... I thought they are on stack. Long run before me. Again thank you, that you care for beginner programer ;) – Kmaczek May 19 '13 at 17:16
  • @Kmaczek: In 32bit x86 on UNIX, the stack layout at entry to a function looks like : `EBP -> [ caller EBP ] ret_addr arg[0] arg[1] arg[2] ...` (if a framepointer was used). The _calling convention_ (ABI) says that if you want to invoke a function that takes parameters, push them onto the stack before the `call` instruction [ and pop them off after that returned ], and that makes `-8(%ebp)` and `-12(%ebp)` the first and second arg to the function. The canonical reference for this (32bit x86 UNIX) is, for all I know, still http://www.sco.com/developers/devspecs/abi386-4.pdf‎ – FrankH. May 21 '13 at 11:47
  • @Kmaczek: 32bit and 64bit on x86/64 use _different_ calling conventions / ABIs. The x86_64 ABI uses `rdi`/`rsi`/`rdx`/`rcx`/`r8`/`r9` (and possibly some `xmm` regs as well) for arguments. Some more references on the differences can be found right here: http://stackoverflow.com/questions/5554856/i386-vs-amd64-abi-differences – FrankH. May 21 '13 at 11:51
  • @FrankH. I just copied taking arguments from stack from my other 32bit function, then I decided to change it to 64. And thought that it is very similar, you just need to change numbers before ebp. I aint chenged them when I posted this, because it was irrelevant for me yet. Then I found some article as you can read above, and it solved my problem. – Kmaczek May 22 '13 at 13:11