在 Mac OSX 上编译 NASM

发布于 12-20 06:32 字数 1545 浏览 6 评论 0 原文

在学校编写编译器时,最后一个里程碑是生成汇编代码。尝试学习 NASM。从头开始, http://www.cs.lmu.edu/~ray /notes/nasmexamples/,尝试编译一个Hello World。

; ----------------------------------------------------------------------------
; helloworld.asm
;
; This is a Win32 console program that writes "Hello, World" on one line and
; then exits.  It needs to be linked with a C library.
; ----------------------------------------------------------------------------

    global  _main
    extern  _printf

    section .text
_main:
    push    message
    call    _printf
    add     esp, 4
    ret
message:
    db      'Hello, World', 10, 0

要在 Windows 下汇编、链接和运行该程序:

nasm -fwin32 helloworld.asm
gcc helloworld.obj
a

在 Linux 下,您需要删除函数名称中的前导下划线,然后执行

nasm -felf helloworld.asm
gcc helloworld.o
./a.out

But I'm on OSX。找到这个小资源:http://salahuddin66.blogspot。 com/2009/08/nasm-in-mac-os-x.html。在 Mac OS X 中,我们应该使用 macho 格式...

nasm -f macho -o hello.o hello.asm

...以及链接器(我们需要指定入口点)...

ld -e main -o hello hello.o

但是当我这样做时...

Undefined symbols:
    "printf", referenced from:
        _main in hello.o
ld: symbol(s) not found for inferred architecture i386

抱歉,我知道需要阅读的内容很多。我怀疑围绕这些部分有很多 NASM 编码器,但值得一试,对吗?如果我能得到任何帮助,我将不胜感激。

Writing a compiler in school, last milestone is generating assembly code. Trying to learn NASM. Starting at the beginning, http://www.cs.lmu.edu/~ray/notes/nasmexamples/, trying to compile a Hello World.

; ----------------------------------------------------------------------------
; helloworld.asm
;
; This is a Win32 console program that writes "Hello, World" on one line and
; then exits.  It needs to be linked with a C library.
; ----------------------------------------------------------------------------

    global  _main
    extern  _printf

    section .text
_main:
    push    message
    call    _printf
    add     esp, 4
    ret
message:
    db      'Hello, World', 10, 0

To assemble, link and run this program under Windows:

nasm -fwin32 helloworld.asm
gcc helloworld.obj
a

Under Linux, you'll need to remove the leading underscores from function names, and execute

nasm -felf helloworld.asm
gcc helloworld.o
./a.out

But I'm on OSX. Found this little resource: http://salahuddin66.blogspot.com/2009/08/nasm-in-mac-os-x.html. In Mac OS X we should use format macho...

nasm -f macho -o hello.o hello.asm

...and for the linker (we need to specify the entry point)...

ld -e main -o hello hello.o

But when I do this...

Undefined symbols:
    "printf", referenced from:
        _main in hello.o
ld: symbol(s) not found for inferred architecture i386

Sorry, I know it's a lot to read. And I doubt there are many NASM coders around these parts, but worth a try right? I'd appreciate any help I can get.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心欲静而疯不止 2024-12-27 06:32:23

您的示例中的程序是 32 位 Windows 程序。如今,编写 64 位程序可能会更好。

要将其转换为 64 位 macOS 程序,您应该确保您拥有最新版本的 nasm,并安装了 gcc。

程序现在应该如下所示:

; ----------------------------------------------------------------------------------------
; This is an macOS console program that writes "Hola, mundo" on one line and then exits.
; It uses puts from the C library.  To assemble and run:
;
;     nasm -fmacho64 hola.asm && gcc hola.o && ./a.out
; ----------------------------------------------------------------------------------------

          global    _main
          extern    _puts

          section   .text
_main:    push      rbx                     ; Call stack must be aligned
          lea       rdi, [rel message]      ; First argument is address of message
          call      _puts                   ; puts(message)
          pop       rbx                     ; Fix up stack before returning
          ret

          section   .data
message:  db        "Hola, mundo", 0        ; C strings need a zero byte at the end

您将注意到一些差异:

  • 在 64 位环境中,第一个参数位于 RDI 中,而不是堆栈上
  • 调用之前,堆栈必须在 16 字节边界上对齐。当进入 main 时,操作系统已将 main 的(8 字节)返回地址放入堆栈中,因此在调用 puts 之前压入 rbx 可以使堆栈重新对齐。
  • 此外,macOS 上的 nasm 需要 rel

The program in your example is a 32-bit Windows program. These days, it's probably better to write a 64-bit program.

To covert this to 64-bit macOS program, you should make sure you have a recent version of nasm, and have gcc installed.

The program should now look like this:

; ----------------------------------------------------------------------------------------
; This is an macOS console program that writes "Hola, mundo" on one line and then exits.
; It uses puts from the C library.  To assemble and run:
;
;     nasm -fmacho64 hola.asm && gcc hola.o && ./a.out
; ----------------------------------------------------------------------------------------

          global    _main
          extern    _puts

          section   .text
_main:    push      rbx                     ; Call stack must be aligned
          lea       rdi, [rel message]      ; First argument is address of message
          call      _puts                   ; puts(message)
          pop       rbx                     ; Fix up stack before returning
          ret

          section   .data
message:  db        "Hola, mundo", 0        ; C strings need a zero byte at the end

You'll note a few differences:

  • In 64 bit land, the first parameter is in RDI, not on the stack
  • The stack must be aligned on a 16-byte boundary before calling. When main is entered, the operating system has placed the (8 byte) return address of main on the stack, so pushing rbx before calling puts serves to get the stack realigned.
  • Also, nasm on macOS needs rel.
过潦 2024-12-27 06:32:23

函数 printf 在某些 C 库中定义(在 Linux 上,例如 /lib/libc.so.6/lib/x86_64-linux- gnu/libc.so.6),所以你需要链接到该库(我不知道它在MacOSX上是什么)

你可以直接"="">系统调用即系统调用(我不了解 MacOSX 的详细信息,但我不知道它们是否公开)。在 Linux 上,Linux Assembly Howto 提供了详细信息。您需要找到适用于您的操作系统的等效详细信息。

(顺便说一句,使用完全免费的软件对于此类任务来说肯定更容易,因为它们的规范和源代码是可用的;对于像 MacOSX 这样的专有软件,您需要从软件提供商处获取,有时它非常昂贵)

Function printf is defined in some C library (on Linux, that would be in e.g. /lib/libc.so.6 or /lib/x86_64-linux-gnu/libc.so.6) so you need to link to that library (I don't know what it is on MacOSX)

You could do directly system calls i.e. syscalls (I don't know the details for MacOSX, and I don't know if they are publicly available). On Linux, the Linux Assembly Howto give the details. You need to find equivalent details for your operating system.

(BTW, using entirely free software is definitely easier for such tasks, because their specification and source code is available; with proprietary software like probably MacOSX is, you need to get the from the software provider, sometimes it is very very expensive)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文