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



我正在尝试使用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,这似乎没有太大的好处。)

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

任何帮助赞赏。


7276
2017-08-05 13:58


起源

您是否尝试使用gcc而不是ld进行链接?它通常更容易,您可以使用C运行时和标准库(例如,有 main 作为切入点)。另一件要尝试的是使用a mach 目标文件格式而不是 elf。 - user786653


答案:


好的,看看你的样本我假设你使用了通用的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)

多数民众赞成的结果 - 小精灵 告诉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

关于 _开始 符号 - 如果你不想创建一个能够的简单程序 使用提供的libc系统功能,你不应该使用 _开始 在al。 这是默认入口点 LD 将在您的libc / libsystem中提供并寻找它。

我建议你尝试更换 _开始 在您的代码中通过类似的东西 '_主要' 并像上面的例子那样链接它。

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汇编指南。


5
2017-09-15 07:29





你需要使用 global start 和 start:没有下划线。此外,你不应该使用 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 flag使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
2017-12-30 18:33





让它变得更容易 gcc 为你做繁重的工作,而不是试图开车 ld 直接地,例如

$ gcc -m32 program.o -o program

2
2017-08-05 14:13





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

1
2017-12-03 16:35