【问题标题】:How to get this simple assembly to run?如何让这个简单的程序集运行?
【发布时间】:2016-03-15 10:35:51
【问题描述】:

这是我第一次尝试用汇编编程。我使用的是 64 位 Mac 操作系统。我也在使用 NASM。我已经四处寻找解决方案,但找不到任何适用于我的机器的方法。

谁能帮我解决这个问题?这是代码和错误,谢谢!

hello.asm

    global start

    section .text
start:
    mov rax, 1
    mov rdi, 1
    mov rsi, message
    mov rdx, 13
    syscall
    mov eax, 60
    xor rdi, rdi
    syscall
message:
    db "Hello, World", 10  

我的执行尝试:

nasm -f macho64 hello.asm -o hello.o
ld -arch i386 -o hello hello.o
./hello

错误

ld: warning: -macosx_version_min not specified, assuming 10.10
ld: warning: ignoring file hello.o, file was built for unsupported file format ( 0xCF 0xFA 0xED 0xFE 0x07 0x00 0x00 0x01 0x03 0x00 0x00 0x00 0x01 0x00 0x00 0x00 ) which is not the architecture being linked (i386): hello.o
Undefined symbols for architecture i386:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture i386

【问题讨论】:

  • 如果您的目标是 64 位代码(可执行文件),显然您正在这样做,请从 LD 命令行中删除 -arch i386
  • @MichaelPetch 成功了,谢谢!但是,现在我收到了Segmentation fault 11。知道如何解决这个问题吗?谢谢。
  • 您的代码适用于 linux,但您显然是在 macos 上。
  • 您似乎在 OS/X 上使用 Linux 系统调用。 64 位代码中 OS/X 上的写入系统调用是 0x20000004 ,退出系统调用是 0x20000001 。在 OS/X 上的 32 位代码中,您从每个系统调用中减去 0x20000000(因此它们在 32 位中是 4 和 1)。
  • 哇,我难以置信的困惑。不过,感谢您解决了我的问题。如果您将其发布为答案,我会接受。

标签: macos assembly linker x86-64 nasm


【解决方案1】:

链接器错误的原因是您使用 NASM 创建了一个 64 位 macho 对象,但随后将 i386 定位为可执行文件。您可能需要的是 64 位可执行文件,可以通过删除 -arch 来完成,如下所示:

ld -o hello hello.o

至于运行程序时的段错误,看来您可能遵循了可能为 Linux 设计的教程。 OS/X 不是基于 Linux,它源自 BSD,因此系统调用不同。我们可以告诉您正在使用 Linux Syscalls,因为 syscall 1 是 sys_writesys_exit 是 rax = 60。不幸的是,这对于操作系统并不相同/X。在 64 位 OS/X 代码中,sys_exit 为 rax=0x20000001,sys_write 为 rax=0x20000004。

您的代码必须更改为:

    global start

    section .data
message: db "Hello, World", 10  

    section .text
start:
    mov rax, 0x20000004
    mov rdi, 1
    mov rsi, message
    mov rdx, 13
    syscall
    mov rax, 0x20000001
    xor rdi, rdi
    syscall

您还会看到我明确声明了一个.data 部分并将您的变量放入其中。在某些环境中,如果将数据变量放在代码中,可能会导致问题。

如果在 OS/X 上创建 32 位代码(在这种情况下您不是),系统调用会从每个代码中减去 0x20000000。所以在 32 位 OS/X 代码中 sys_exit 是 eax=0x1 而 sys_write 是 eax=0x4 。

可以在Apple information 中找到 OS/X 上所有系统调用(及其参数)的参考。对于 64 位汇编代码,只需将 0x20000000 添加到图表第一列中的每个数字即可。

您可能希望找到有关 Syscall 的 64 位 OS/X 教程。这是simple one

【讨论】:

    猜你喜欢
    • 2021-08-29
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 2011-05-08
    • 1970-01-01
    • 2018-10-08
    • 2016-01-14
    相关资源
    最近更新 更多