GNU Linker and architecture i386 - c

So I'm running on OS X and I want to link two Mach-O objects i386.
The first is generated from NASM (it's an assembly file)
nasm -f macho -o kernel.o kernel.asm
The second is generated from GCC
gcc -c -arch i386 screen.c
But when I try to link them...
ld -o myprogram screen.o kernel.o
...I get this error :
Undefined symbols for architecture i386:
"print", referenced from:
start in kernel.o
ld: symbol(s) not found for inferred architecture i386
I don't understand why, because my two files are Mach-O object i386 :
$ file screen.o
screen.o: Mach-O object i386
$ file kernel.o
kernel.o: Mach-O object i386
If you need it, here's kernel.asm :
[BITS 32]
EXTERN print
GLOBAL start
start:
mov eax, msg
push eax
call print
pop eax
end:
jmp end
msg db 'Hello world!', 10, 0
And here's screen.c :
void putcar(uchar c)
{
/* Some code here */
}
void print(char *string)
{
while(*string != 0){
putcar(*string);
string++;
}
}

You need to use the symbol _print in your asm file, i.e.
start:
mov eax, msg
push eax
call _print
pop eax
This is because C function names get a leading underscore when compiled.

Related

How to call external c file from assembly?

I'm tried this below tools, to call 2 files
My idea was to execute the function from c using assembler and create a bin file
nasm -f elf32 boot3.s -o boot3.o // convert asm file to object
gcc -c bootloader3.c -o bootloader3.o // convert c file to object
gcc boot3.o bootloader3.o -o boot3.bin // make bin file
boot3.s
section .text
bits 16
global _start ; Declare the entry point symbol
extern main ; Declare the main function as external
_start:
cli ; Disable the interrupts
call main ; Call the main function
hlt ; Halt the CPU
bootloader3.c
#include <stdio.h>
void main() {
printf("Hello, World!\n");
return;
}
My error: Error Image
Update 05.01.23
I tried to use a similar method, but with other commands, unfortunately another attempt also failed.
boot.s
bits 16
extern main
start:
cli ; Disable the interrupts
mov si, msg ; SI now points to our message
mov ah, 0x0E ; Indicate BIOS we're going to print chars
.loop lodsb ; Loads SI into AL and increments SI [next char]
or al, al ; Checks if the end of the string
jz halt ; Jump to halt if the end
int 0x10 ; Otherwise, call interrupt for printing the char
jmp .loop ; Next iteration of the loop
halt: hlt ; CPU command to halt the execution
msg: db "Hello, World!", 0 ; Our actual message to print
section .text
global puts
puts:
; Insert code for the puts function here
times 510 - ($ - $$) db 0
; Add the boot signature
dw 0xAA55
bootloader.c
//extern void puts(const char* str);
int main(void)
{
puts("Hello user");
return 0;
}
Compile using tools
First Step
nasm -f elf64 boot.s -o boot.o
gcc -c -m32 -o bootloader.o bootloader.c
ld -Ttext=0x7C00 -o boot.elf boot.o bootloader.o
Second Step
nasm -f bin boot.s -o boot.o
gcc -c -m32 -o bootloader.o bootloader.c
gcc -m32 -nostdlib -nostartfiles -Wl,-Ttext,0x7C00 boot.o bootloader.c -o boot.elf
Third Step
nasm -f elf32 boot.s -o boot.o
gcc -c -m32 -o bootloader.o bootloader.c
ld -Ttext=0x7C00 -o boot.elf boot.o bootloader.o
My Error:
On First & Third step
ld: bootloader.o:bootloader.c:(.text+0xa): undefined reference to `__main' ld: bootloader.o:bootloader.c:(.text+0x16): undefined reference to `puts'
On Seconds step
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Klubuntu\AppData\Local\Temp\ccojaMyU.o:bootloader.c:(.text+0xa): undefined reference to `__main' c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: C:\Users\Klubuntu\AppData\Local\Temp\ccojaMyU.o:bootloader.c:(.text+0x16): undefined reference to `puts' collect2.exe: error: ld returned 1 exit status
Sorry for all grammar mistakes
Thanks from above help

Archive has no index; run ranlib to add one (when linking with a .a containing a MachO64 object file on Linux)

I tried to create a library and test it, but an error occurred.
error code:
./libasm.a: error adding symbols: Archive has no index; run ranlib to add one
collect2: error: ld returned 1 exit status
I compiled it like this.
nasm -f macho64 ft_strlen.s -o ft_strlen.o
ar rcs libasm.a ft_strlen.o
ranlib libasm.a
gcc main.c libasm.a
Below is the source file
;ft_strlen.s
segment .text
global ft_strlen
ft_strlen:
mov rax, 0
jmp count
count:
cmp BYTE [rdi + rax], 0
je exit
inc rax
jmp count
exit:
ret
/*main.c*/
#include <stdio.h>
int ft_strlen(char *str);
int main(void)
{
char *str = "hello world";
printf("%d \n", ft_strlen(str));
}
I am using ubuntu installed on wsl.
What am I doing wrong?
Generate object files for Linux-based operating system (or perhaps more correctly, and ELF64 system) with nasm -f elf64 ft_strlen.s -o ft_strlen.o
For more info nasm -hf to see all valid output formats for nasm -f
Small tip: ranlib command is not needed because ar s is already indexing the library.

Commands to compile ASM file with C program [duplicate]

This question already has an answer here:
32-bit absolute addresses no longer allowed in x86-64 Linux?
(1 answer)
Closed 4 years ago.
with à 64 Linux system and using NASM.
I'm trying too link my ASM (hello.asm) file with a C file (main.c) and compile to a execution file.
I create a ASM file that print "Hello" with printf by using printHello function.
extern printf, exit
section .data
format db "Hello", 10, 0
section .text
global printHello
printHello:
sub rsp, 8
mov rsi, 0x12345677
mov rdi, format
xor rax, rax
call printf
mov rdi, 0
call exit
I create a simple main.c and call my function "printHello" to print "Hello"
#include <stdio.h>
void printHello();
int main()
{
printHello();
}
My command for compile :
$ nasm -f elf64 hello.asm
$ gcc -c main.c
$ gcc -o executable main.o hello.o
$ ./executable
And it prints :
./executable: Symbol `printf' causes overflow in R_X86_64_PC32 relocation
./executable: Symbol `exit' causes overflow in R_X86_64_PC32 relocation
[1] 6011 segmentation fault ./executable
I'm already learning ASM. Is the problem come from my command or my code ?
I resolved the problem by using your #Jester solution :
gcc -no-pie -o executable main.o hello.o
and thanks Ped7g for explanation.

Linking with cygwin

I have a small program that's made of an assembly function and a C function which calls it.
Now the program compiles and works perfectly on a UNIX system but when using the makefile in cygwin i get the following error:
gcc -m32 -g -c -o main.o main.c
gcc -g -m32 -o ass0 main.o myasm.o
main.o: In function main':
/cygdrive/c/ass0/main.c:15: undefined reference to_strToLeet'
collect2: error: ld returned 1 exit status
makefile:3: recipe for target 'ass0' failed
make: *** [ass0] Error 1
code of the main.c file :
#include <stdio.h>
# define MAX_LEN 100 // Maximal line size
extern int strToLeet (char*);
int main(void) {
char str_buf[MAX_LEN];
int str_len = 0;
printf("Enter a string: ");
fgets(str_buf, MAX_LEN, stdin); // Read user's command line string
str_len = strToLeet (str_buf); // Your assembly code function
printf("\nResult string:%s\nNumber of letters converted to Leet: %d\n",str_buf,str_len);
}
start of assembly code:
section .data ; data section, read-write
an: DD 0 ; this is a temporary var
section .text ; our code is always in the .text section
global strToLeet ; makes the function appear in global scope
extern printf ; tell linker that printf is defined elsewhere
strToLeet: ; functions are defined as labels
push ebp ; save Base Pointer (bp) original value
mov ebp, esp ; use base pointer to access stack contents
pushad ; push all variables onto stack
mov ecx, dword [ebp+8] ; get function argument
makefile code :
all: ass0
ass0: main.o myasm.o
gcc -g -m32 -o ass0 main.o myasm.o
main.o: main.c
gcc -m32 -g -c -o main.o main.c
myasm.o: myasm.s
nasm -g -f elf -l ass0list -o myasm.o myasm.s
help would be most appriciated
Solved by user 'tvin' -
Try to modify your prototype to become extern int strToLeet (char*) asm ("strToLeet"); – tivn

Linking error when compiling basic x86 code with gcc

I am attempting to write very basic x86 code and call it in a C program. I'm running OSX 10.8.2. Here is the code I have:
start.c:
#include <stdio.h>
void _main(); // inform the compiler that Main is an external function
int main(int argc, char **argv) {
_main();
return 0;
}
code.s
.text
.globl _main
_main:
ret
I run the following commands to attempt compilation:
gcc -c -o code.o code.s
gcc -c -o start.o start.c
gcc -o start start.o code.o
Which then returns this output after the final command:
Undefined symbols for architecture x86_64:
"__main", referenced from:
_main in start.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Am I missing something in my compiler calls? Do I need to update something/install something different? I just can't find a definitive answer anywhere since this is such a general output. Thanks!
You need an extra underscore in your asm _main symbol:
.text
.globl __main
__main:
ret
C symbols get an underscore prefix when compiled, so your C main is actually _main and an extern C _main actually needs to be defined as __main if you write it in asm.

Resources