无法在Mac OS X中使用ld链接汇编文件

13


我正在尝试在64位Mac OS X Lion上运行一个基本的汇编文件,使用默认安装的nasm和ld(随Xcode一起安装)。

我编写了一个汇编文件,它打印一个字符,并使用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似乎没有起到什么作用。)

我有点困惑,不知道如何使用ld将目标文件成功链接到二进制文件,并且我认为我只是缺少一些代码(或对nasm或ld的参数),可以使它们达成一致。

感谢任何帮助。


你尝试过使用gcc而不是ld进行链接吗?这通常更容易,而且你可以使用C运行时和标准库(例如将main作为入口点)。另一个尝试的方法是使用mach对象文件格式而不是elf - user786653
4个回答

6

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

#!/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 警告,我也每次都会遇到,并且不确定原因,但在运行可执行文件时一切似乎都正常。

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系统函数,那么你不应该使用_start。这是默认的入口点,ld将会查找,并且通常包含在你的libc/libsystem中。
我建议你尝试用类似'_main'的东西来替换你代码中的_start,并按照上面的例子链接它。
一个基于libc的nasm汇编模板可能如下所示:
;---------------------------------------------------
.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汇编指南。

2

也许最好让gcc为您完成大部分工作,而不是直接使用ld,例如:

$ gcc -m32 program.o -o program

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接