12


我正在尝试使用 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 _startin .section text,在上面_start,这似乎并没有多大用处。)

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

任何帮助表示赞赏。

4

4 回答 4

6

您需要使用global startand 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标志使 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警告,我也每次都收到,我不知道为什么,但是当我运行可执行文件时一切似乎都很好。

于 2011-12-30T18:33:06.140 回答
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 中提供。

我建议您尝试将代码中的_start替换为'_main' 之类的内容,并像上面的示例一样链接它。

用于 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 组装指南。

于 2011-09-15T07:29:27.627 回答
2

gcc你做繁重的工作可能比ld直接开车更容易,例如

$ gcc -m32 program.o -o program
于 2011-08-05T14:13:51.037 回答
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
于 2015-12-03T16:35:33.573 回答