Martimc
Martimc

Reputation: 3

Linking a c function and a asm assembly file

I have a postfix program that does a while loop and prints 10 numbers, and it needs an extern print function which i defined, but for some reason after i create the object file if i do ld -m elf_i386 -s -o p11 p11.o print.o it gives me some strange errors.

what i want to do is link those files and create an executable that prints values from 1 to 10, but for some reason its giving me those errors when clearly what i want is use that c function to print those values

ps: if i use gcc -m32 -o p11 p11.o print.o i get the following error:

/usr/bin/ld: p11.o: warning: relocation in read-only section `.text'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib32/Scrt1.o: in function `_start':
(.text+0x22): undefined reference to `main'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status

commands:

$ nasm -f elf32 p11.asm -o p11.o
$ gcc -m32 -o print.o -c print.c
$ ld -m elf_i386 -s -o p11 p11.o print.o

Error:

ld: warning: cannot find entry symbol _start; defaulting to 0000000008049000
ld: print.o: in function `print':
print.c:(.text+0x21): undefined reference to `printf'

I dont get why because printf is defined in c and clearly coded somewhere

postfix program:

EXTERN print ; extern print(int)
DATA
ALIGN
GLOBAL ix, OBJ; static ix
LABEL ix
SINT 0; static ix=0
TEXT
ALIGN
INT 0
DUP32
ADDR ix
STINT
TRASH 4
ALIGN
LABEL whilecond
ADDR ix
LDINT
INT 10
LT
JZ endwhile
ADDR ix
LDINT
INT 1
ADD
DUP32
ADDR ix
STINT
TRASH 4
ADDR ix
LDINT
CALL print
TRASH 4
JMP whilecond
ALIGN
LABEL endwhile

assembly program:

extern  print
segment .data
align   4
global  ix:object
ix:
    dd  0
segment .text
align   4
    push    dword 0
    push    dword [esp]
    push    dword $ix
    pop ecx
    pop eax
    mov [ecx], eax
    add esp, 4
align   4
whilecond:
    push    dword $ix
    pop eax
    push    dword [eax]
    push    dword 10
    pop eax
    xor ecx, ecx
    cmp [esp], eax
    setl    cl
    mov [esp], ecx
    pop eax
    cmp eax, byte 0
    je  near endwhile
    push    dword $ix
    pop eax
    push    dword [eax]
    push    dword 1
    pop eax
    add dword [esp], eax
    push    dword [esp]
    push    dword $ix
    pop ecx
    pop eax
    mov [ecx], eax
    add esp, 4
    push    dword $ix
    pop eax
    push    dword [eax]
    call    print
    add esp, 4
    jmp dword whilecond
align   4
endwhile:

c program:

#include <stdio.h>

void print(int num)
{
    printf("%d\n",num);
}

Upvotes: 0

Views: 232

Answers (1)

Employed Russian
Employed Russian

Reputation: 213957

I dont get why because printf is defined in c and clearly coded somewhere

Because you are not linking that somewhere (namely, you are not linking with libc).

On UNIX systems, you should never use ld to link anything (with the exceptions of the kernel and boot loader).

Instead you should always use appropriate compiler driver (gcc here). Gcc will automatically add -lc to the link line.

P.S. you should also define the main program -- it's unclear how you expect your code to be invoked, since you defined nighter main, nor _start symbol.

if i use gcc -m32 -o p11 p11.o print.o i get the following error:

Your gcc is configured to build PIE binaries by default, but your assembly is not written to be compatible with PIE.

Add the -fno-pie to your compile lines and -no-pie flag to your link line.

Upvotes: 2

Related Questions