无法使用ld在Mac OS X中链接程序集文件

时间:2011-08-05 13:58:30

标签: macos assembly nasm ld object-files


我正在尝试使用64位Mac OS X Lion运行一个基本的程序集文件,使用默认安装在Xcode上的nasm和ld。

我已经编写了一个汇编文件,可以打印一个字符,然后我使用nasm构建它。

nasm -f elf -o program.o main.asm

但是,当我将它与ld链接时,它会因为相当多的错误/警告而失败:

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

所以,我试图解决其中的一些问题,并没有取得任何进展。

这是我尝试过的一件事:

ld -arch i386 -e _start -o program program.o

我认为这会奏效,但我错了。

如何使目标文件成为nasm和ld同意的兼容架构?

另外,你如何定义程序中的入口点(现在我在global _start使用.section text_start以上{{1}}似乎做得很好。)

关于如何使用ld成功将目标文件链接到二进制文件,我有点困惑,我想我只是缺少一些会让他们同意的代码(或者是nasm或ld的参数)。

任何帮助表示感谢。

4 个答案:

答案 0 :(得分:5)

好的,看看你的样本我假设你使用了通用的nasm或linux汇编教程 您需要注意的第一件事是由nasm创建的二进制格式 你的帖子说明:

ld: warning: ignoring file program.o, file was built for unsupported file format which is not the architecture being linked (x86_64)

这是' -f elf '参数的结果,它告诉nasm你想要一个32位ELF对象(例如linux的情况)。但是,因为你在OSX上你想要的是一个Mach-O对象。

尝试以下方法:

nasm -f macho64 -o program.o main.asm
gcc -o program program.o

或者如果您不想创建32位二进制文​​件:

nasm -f macho32 -o program.o main.asm
gcc -m32 -o program program.o

关于 _start 符号 - 如果您不想创建一个能够执行的简单程序 要使用提供的libc系统功能,你不应该在al使用 _start 。 这是 ld 将在libc / libsystem中提供的默认入口点。

我建议您尝试用'_ main'替换代码中的 _start 并像上面的例子那样链接它。

nasm的基于libc的通用程序集模板可能如下所示:

;---------------------------------------------------
.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

除此之外,我应该提一下,你在OSX上做的任何调用都需要使用对齐的堆栈帧,否则你的代码就会崩溃。
这里有一些很好的教程 - 尝试搜索OSX汇编指南。

答案 1 :(得分:5)

您需要使用global startstart:无下划线。此外,您不应该使用elf作为拱门。这是我用来在Mac OS X上组装我的x86-64 NASM程序的bash脚本:

#!/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

如果您有一个名为foo.s的文件,则此脚本将首先运行

nasm -f macho64 -Ox foo.s

将创建foo.o-Ox标志使NASM通过跳跃进行一些额外的优化(即使它们短,近或远),这样你就不必自己动手了。我使用的是x86-64,所以我的代码是64位,但看起来你正试图组装32位。在这种情况下,您将使用-f macho32。有关有效输出格式的列表,请参阅nasm -hf

现在,目标文件将被链接:

ld -macosx_version_min 10.7 foo.o -o foo

我已将-macosx_version_min选项设置为静音NASM并阻止警告。您不必将其设置为Lion(10.7)。这将创建一个名为foo的可执行文件。运气好的话,输入./foo并点击返回应该运行你的程序。

关于ld: warning: symbol dyld_stub_binder not found, normally in libSystem.dylib警告,我每次都会得到这个警告,但我不确定原因,但是当我运行可执行文件时,一切似乎都很好。

答案 2 :(得分:2)

gcc为你做繁重的工作可能更容易,而不是试图直接驾驶ld,例如。

$ gcc -m32 program.o -o program

答案 3 :(得分:1)

mac gcc编译器不会链接elf对象。你需要一个交叉编译器......

http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux

然后你可以继续进行类似的事情......

/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