nasm-无法将macOS Mojave上的对象文件与ld链接

nasm-无法将macOS Mojave上的对象文件与ld链接,macos,assembly,nasm,ld,Macos,Assembly,Nasm,Ld,我正在尝试组装一个简单的Hello World,它在以前的macOS版本中运行良好: global start section .text start: mov rax, 0x02000004 mov rdi, 1 mov rsi, msg mov rdx, 13 syscall mov rax, 0x02000001

我正在尝试组装一个简单的Hello World,它在以前的macOS版本中运行良好:

        global   start
        section  .text
start:  mov      rax, 0x02000004
        mov      rdi, 1
        mov      rsi, msg
        mov      rdx, 13
        syscall
        mov      rax, 0x02000001
        xor      rdi, rdi
        syscall

        section  .data
msg:    db       "Hello world!", 10
然后我像以前一样使用nasm和ld:

$ nasm -f macho64 hello.asm
$ ld hello.o -o hello
但ld给了我以下错误:

ld: warning: No version-min specified on command line
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for inferred architecture x86_64
我尝试将start切换到_main,但得到以下结果:

ld: warning: No version-min specified on command line
ld: dynamic main executables must link with libSystem.dylib for inferred architecture x86_64
甚至不知道这可能意味着什么。

ld需要-lSystem标志来防止抛出此错误。它还需要-macosx_version_min来删除警告。使用ld的正确方法是:ld hello.o-o hello-macosx\u version\u min 10.13-lSystem

在macOS 11及更高版本上更新后,还需要传递-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib,以便它正确定位-lSystem库。如果需要,您可以使用-L$xcode select-p/SDKs/MacOSX.sdk/usr/lib动态评估正确的路径。

除了上面的@Verloren答案之外

我在macOS 11.1上遇到了一个问题,其中flag-lSystem无法找到libSystem.dylib,出现了错误

ld: library not found for -lSystem
我在macOS Big Sur上发现了这一点,引自链接:

macOS Big Sur 11.0.1中新增了该系统,该系统附带内置动态 所有系统提供的库的链接器缓存。作为这一变化的一部分, 文件系统上不再存在动态库的副本。 试图通过查找来检查动态库是否存在的代码 对于路径上的文件或枚举目录将失败

动态库的所有副本都不在usr/lib/和类似文件中,因此默认情况下flag-lSystem找不到libSystem.dylib

解决方案是更新/安装最新版本的命令行工具(如果还没有),并将ld命令的flag-L设置为/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib

因此,完整命令将如下所示:

ld hello.o -o hello -macosx_version_min 11.0 -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem
更简单的答案。ld默认为动态链接,并尝试加载正在查找main的crt1。因此,请指定静态链接

% ld -e start -static hello.o -o hello
% ./hello
Hello world!

这就是为什么通常使用cc hello.o-o hello链接,因为C编译器知道如何将对象文件链接到可执行文件中。顺便说一句,您应该使用lea rdi,[rel msg],而不是需要运行时重新定位的mov rdi、imm64绝对形式。10.13 as min版本ld将切换到加载命令LC_主入口点约定,由dyld处理。您的系统退出调用强制进程退出,而不给dyld刷新缓冲区的机会,这与系统写入调用无关,但与printf无关。在这里查看我的答案:那么运行hello.asm的完整命令是什么?我正在使用相同的教程,只是替换你的ld不起作用。对于学习LC_MAIN,谢谢,这真的很有用。