I've written an assembly file, which prints a character, and I got it to build using nasm.
nasm -f elf -o program.o main.asm
However, when I go to link it with ld, it fails with quite a few errors/warnings:
ld -o program program.o
ld: warning: -arch not specified
ld: warning: -macosx_version_min not specificed, assuming 10.7
ld: warning: ignoring file program.o, file was built for unsupported file format which is not the architecture being linked (x86_64)
ld: warning: symbol dyld_stub_binder not found, normally in libSystem.dylib
ld: entry point (start) undefined. Usually in crt1.o for inferred architecture x86_64
So, I tried to rectify a few of these issues, and got nowhere.
Here's one of things I've tried:
ld -arch i386 -e _start -o program program.o
Which I thought would work, but I was wrong.
How do you make the object file a compatible architecture that nasm and ld will agree with?
Also, how would you define the entry point in the program (right now I'm usingglobal _start
in .section text
, which is above _start
, which doesn't seem to do much good.)
I'm a bit confused as to how you would successfully link an object file to a binary file using ld, and I think I'm just missi开发者_开发百科ng some code (or argument to nasm or ld) that will make them agree.
Any help appreciated.
You need to use global start
and start:
, no underscore. Also, you should not be using elf
as the arch. Here is a bash script I use to assemble my x86-64 NASM programs on Mac OS X:
#!/bin/bash
if [[ -n "$1" && -f "$1" ]]; then
filename="$1"
base="${filename%%.*}"
ext="${filename##*.}"
nasm -f macho64 -Ox "$filename" \
&& ld -macosx_version_min 10.7 "${base}.o" -o "$base"
fi
If you have a file called foo.s
, this script will first run
nasm -f macho64 -Ox foo.s
Which will create foo.o
. The -Ox
flag makes NASM do some extra optimization with jumps (i.e. making them short, near or far) so that you don't have to do it yourself. I'm using x86-64, so my code is 64-bit, but it looks like you're trying to assemble 32-bit. In that case, you would use -f macho32
. See nasm -hf
for a list of valid output formats.
Now, the object file will be linked:
ld -macosx_version_min 10.7 foo.o -o foo
I've set the -macosx_version_min
option to quiet NASM down and prevent a warning. You don't have to set it to Lion (10.7). This will create an executable called foo
. With any luck, typing ./foo
and hitting return should run your program.
In regard to the ld: warning: symbol dyld_stub_binder not found, normally in libSystem.dylib
warning, I get that every time too and I'm not sure why, but everything seems fine when I run the executable.
OK, looking at your samples I assume you either used a generic nasm or linux assembly tutorial.
The first thing you need to take care of is the binary format created by nasm.
Your post states:
ld: warning: ignoring file program.o, file was built for unsupported file format which is not the architecture being linked (x86_64)
Thats the result of the '-f elf' parameter which tells nasm you want a 32bit ELF object (which would be the case for e.g. linux). But since you're on OSX what you want is a Mach-O object.
Try the following:
nasm -f macho64 -o program.o main.asm
gcc -o program program.o
Or if you wan't to create a 32bit binary:
nasm -f macho32 -o program.o main.asm
gcc -m32 -o program program.o
Regarding the _start symbol - if you wan't to create a simple program that will be able to use the provided libc system functions then you shouldn't use _start at al. It's the default entry point ld will look for and normaly it's provided in your libc / libsystem.
I suggest you try to replace the _start in your code by something like '_main' and link it like the example above states.
A generic libc-based assembly template for nasm could look like this:
;---------------------------------------------------
.section text
;---------------------------------------------------
use32 ; use64 if you create 64bit code
global _main ; export the symbol so ld can find it
_main:
push ebp
mov ebp, esp ; create a basic stack frame
[your code here]
pop ebp ; restore original stack
mov eax, 0 ; store the return code for main in eax
ret ; exit the program
In addition to this I should mention that any call's you do on OSX need to use an aligned stack frame or your code will just crash.
There are some good tutorials on that out there too - try searching for OSX assembly guide.
It's probably easier just to let gcc
do the heavy lifting for you, rather than trying to drive ld
directly, e.g.
$ gcc -m32 program.o -o program
The mac gcc compiler won't link elf objects. You need a cross compiler...
http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux
Then you can proceed with something similar to this...
/usr/local/gcc-4.8.1-for-linux32/bin/i586-pc-linux-ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o
精彩评论