0

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);
}
Martimc
  • 3
  • 3

1 Answers1

2

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.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • 1
    `ld` can be used to link a hand-written static executable that *doesn't* use any libraries, just defines its own `_start` and uses system calls directly. But yes, if you use any C libraries or want to link CRT code, you should let the C compiler's front-end do it, perhaps with `gcc -no-pie -fno-pie` if you wrote a `main`. (Writing your own `_start` but using libc functions depends on dynamic linker support, and/or manually calling libc init functions from your _start.) – Peter Cordes Jun 14 '22 at 01:59
  • how do i do that? – Martimc Jun 14 '22 at 15:28
  • @Peter Cordes it worked in compiling but i still get the error `(.text+0x22): undefined reference to main` how can i do a main that starts my asm code and includes the print function? – Martimc Jun 14 '22 at 15:49
  • @Martimc: You can't link that program without libc; your C code calls printf, therefore you need to link your program against a library that defines that symbol. The compiler-generated asm will include a `call printf` or `call printf@plt`, so its object file symbol table will include a reference to that symbol, just like you you have `.extern print` in the file that does `call print`. And you couldn't link that file into an executable without a .o that defines `print`. – Peter Cordes Jun 14 '22 at 21:56
  • @Martimc: If you wanted to make a stand-alone static executable with no libraries, you'd have to do something like [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) – Peter Cordes Jun 14 '22 at 21:58