sav*_*ger 5 compiler-construction macos linker gcc 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
Run Code Online (Sandbox Code Playgroud)
要在 Windows 下组装、链接和运行此程序:
nasm -fwin32 helloworld.asm
gcc helloworld.obj
a
Run Code Online (Sandbox Code Playgroud)
在 Linux 下,您需要从函数名称中删除前导下划线,然后执行
nasm -felf helloworld.asm
gcc helloworld.o
./a.out
Run Code Online (Sandbox Code Playgroud)
但我在 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
Run Code Online (Sandbox Code Playgroud)
...对于链接器(我们需要指定入口点)...
ld -e main -o hello hello.o
Run Code Online (Sandbox Code Playgroud)
但是当我这样做时...
Undefined symbols:
"printf", referenced from:
_main in hello.o
ld: symbol(s) not found for inferred architecture i386
Run Code Online (Sandbox Code Playgroud)
抱歉,我知道要读很多书。我怀疑这些部分周围有很多 NASM 编码器,但值得一试,对吗?我很感激我能得到的任何帮助。
您的示例中的程序是 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
Run Code Online (Sandbox Code Playgroud)
您会注意到一些差异:
rbx
在调用之前压入puts
可以使堆栈重新对齐。rel
.函数printf
是在某些 C 库中定义的(在 Linux 上,将在例如/lib/libc.so.6
或中/lib/x86_64-linux-gnu/libc.so.6
),因此您需要链接到该库(我不知道它在 MacOSX 上是什么)
您可以直接进行系统调用,即系统调用(我不知道 MacOSX 的详细信息,也不知道它们是否公开)。在 Linux 上,Linux Assembly Howto提供了详细信息。您需要找到适用于您的操作系统的等效详细信息。
(顺便说一句,使用完全免费的软件对于此类任务来说肯定更容易,因为它们的规范和源代码是可用的;对于像 MacOSX 这样的专有软件,您需要从软件提供商处获取,有时它非常昂贵)