在Mac OSX上编译NASM
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Mac OSX上编译NASM相关的知识,希望对你有一定的参考价值。
在学校编写编译器,最后一个里程碑是生成汇编代码。试图学习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
但我在OSX上。找到这个小资源:http://salahuddin66.blogspot.com/2009/08/nasm-in-mac-os-x.html。在Mac OS X中我们应该使用格式化的...
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编码器,但值得一试吗?我很感激我能得到任何帮助。
函数printf
在某些C库中定义(在Linux上,例如/lib/libc.so.6
或/lib/x86_64-linux-gnu/libc.so.6
),因此您需要链接到该库(我不知道它在MacOSX上是什么)
你可以直接做system calls,即syscalls(我不知道MacOSX的细节,我不知道它们是否公开可用)。在Linux上,Linux Assembly Howto提供了详细信息。您需要找到适用于您的操作系统的详细信息。
(顺便说一句,使用完全免费的软件对于此类任务来说肯定更容易,因为他们的规范和源代码是可用的;使用像MacOSX这样的专有软件,你需要从软件提供商那里获得,有时它非常昂贵)
您的示例中的程序是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字节)返回地址放在堆栈上,因此在调用
rbx
之前按puts
可以使堆栈重新排列。 - 另外,macOS上的nasm需要
rel
。
以上是关于在Mac OSX上编译NASM的主要内容,如果未能解决你的问题,请参考以下文章
GCC 在尝试在 OSX 10.6 上编译 64 位代码时死了