Mac OSX下无法编译NASM Hello World程序问题求助
Hey Liam, let's get that NASM Hello World up and running on macOS! Making the jump from MASM/Irvine to NASM on a Unix-like system can throw you for a loop with different calling conventions, executable formats, and syscall rules—so let's break this down step by step.
First, Let's Fix Your Hello World Code
The most common issues here are incorrect entry points, wrong syscall numbers, or missing stack setup. Here's a working 64-bit Mach-O version that uses direct syscalls (no libc dependency):
; hello.asm section .data msg db "Hello, World!", 0x0A ; 0x0A adds a newline at the end len equ $ - msg ; Calculate length of our string automatically section .text global _main ; macOS requires the entry point to be _main (not _start like Linux) _main: ; Syscall: write(1, msg, len) mov rax, 0x2000004 ; macOS syscall number for write (0x4 + 0x2000000 prefix) mov rdi, 1 ; File descriptor 1 = stdout mov rsi, msg ; Pointer to our message string mov rdx, len ; Length of the string syscall ; Invoke the syscall ; Syscall: exit(0) mov rax, 0x2000001 ; macOS syscall number for exit mov rdi, 0 ; Exit code 0 (success) syscall
Compile and Link Correctly
Your initial compile command is actually right—you just missed the linking step to turn the object file into a runnable executable:
- Compile the assembly to a Mach-O object file:
nasm -f macho64 -o hello.o hello.asm - Link the object file into an executable (we need to specify the macOS version and link against the system library):
ld -macosx_version_min 10.14 -o hello hello.o -lSystem - Run it:
./hello
If You Prefer Using Libc (Like printf)
If you want to use standard library functions instead of raw syscalls, here's a version that uses printf—and we can use gcc to handle linking more easily:
; hello-printf.asm section .data msg db "Hello, World!", 0x0A, 0 ; Null-terminated string (required for printf) section .text extern _printf ; Declare we're using printf from libc global _main _main: push rbp ; Set up a stack frame (required for calling libc functions) mov rbp, rsp lea rdi, [rel msg] ; First argument to printf: pointer to our string call _printf ; Call the printf function mov eax, 0 ; Return 0 from main (success) leave ret
Compile and link with gcc (it handles all the system library and version stuff automatically):
nasm -f macho64 -o hello-printf.o hello-printf.asm gcc -o hello-printf hello-printf.o ./hello-printf
Common Pitfalls You Might Have Hit
- Wrong entry point: Unlike Linux (which uses
_start), macOS Mach-O executables require_mainas the entry point. - Incorrect syscall numbers: macOS adds a
0x2000000prefix to all syscall numbers (e.g.,writeis0x2000004instead of just0x4like Linux). - Skipping the link step: Compiling with
nasmonly creates an object file—you needldorgccto turn it into a runnable program. - Malformed strings: For
printf, your string must be null-terminated (add a0at the end), or you'll get garbage output.
内容的提问来源于stack exchange,提问作者Liam

