- NASM Manual - for the syntax
- What are the calling conventions for UNIX & Linux system calls on x86-64 - comparison
- AMD64 ABI reference - A.2.1 - for the actual x86_64 calling convention
- X86 calling conventions - moar calling conventions
- Mac OS X syscalls reference
Last active
November 7, 2024 06:51
-
-
Save FiloSottile/7125822 to your computer and use it in GitHub Desktop.
NASM Hello World for x86 and x86_64 Intel Mac OS X (get yourself an updated nasm with brew)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; /usr/local/bin/nasm -f macho 32.asm && ld -macosx_version_min 10.7.0 -o 32 32.o && ./32 | |
global start | |
section .text | |
start: | |
push dword msg.len | |
push dword msg | |
push dword 1 | |
mov eax, 4 | |
sub esp, 4 | |
int 0x80 | |
add esp, 16 | |
push dword 0 | |
mov eax, 1 | |
sub esp, 12 | |
int 0x80 | |
section .data | |
msg: db "Hello, world!", 10 | |
.len: equ $ - msg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; /usr/local/bin/nasm -f macho64 64.asm && ld -macosx_version_min 10.7.0 -lSystem -o 64 64.o && ./64 | |
global start | |
section .text | |
start: | |
mov rax, 0x2000004 ; write | |
mov rdi, 1 ; stdout | |
mov rsi, msg | |
mov rdx, msg.len | |
syscall | |
mov rax, 0x2000001 ; exit | |
mov rdi, 0 | |
syscall | |
section .data | |
msg: db "Hello, world!", 10 | |
.len: equ $ - msg |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A couple of things about the hello world above.
OS X deprecated syscall. It still works but if you look at the compiled code, the gas compiler is replacing the syscall with imported function calls. Since they are function calls, you are supposed to align stack. It seems to work without it, but if you want to align the stack to a 16 byte boundary without worrying about where it is when the program starts, you can AND the stack pointer with FFFFFFFFFFFFFFF0 at entry.
I think exported functions have to have _ in front of them in gas. Something to do with avoiding name collisions with imports maybe..
Mac also changed where the system libraries are for security reasons for Big Sur. If you want your program to run on a system that doesn't have the xtools command line tools installed, you have to link in a certain way. I posted a question about this on the Mac developer forums and Eskimo explained how to figure it out using -v with a c program. The link to the discussion is here: https://developer.apple.com/forums/thread/669094
The short answer is, this link command works: ld -e _myhelloworldstart -no_uuid -no_eh_labels -demangle -dynamic -arch x86_64 -platform_version macos 11.0.0 11.1 -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -o helloworld64 -L/usr/local/lib helloworld64.o -lSystem
The key is the -syslibroot command.
I think if you use OTOOL to look what the library is linking against, you can see what's going on.
This hello world works for gas with the filename helloworld64gas.s:
.text
_omyhelloworldmessage:
.asciz "\nHello World!\n\n"
.globl _myhelloworldstart
_myhelloworldstart:
/* align the stack regardless of where it is when this function is called */
andq $0xfffffffffffffff0, %rsp
movq $1, %rdi /* stdout handle /
leaq _omyhelloworldmessage(%rip), %rsi / pmessageaddress /
movq $15, %rdx / messagelength */
call _write
call _exit
with this assembly command:
as -mmacosx-version-min=11.0 ./helloworld64gas.s -o helloworld64gas.o
and this link command:
ld -e _myhelloworldstart -no_uuid -no_eh_labels -demangle -dynamic -arch x86_64 -platform_version macos 11.0.0 11.1 -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -o helloworld64gas -L/usr/local/lib helloworld64gas.o -lSystem
If you are interested, and up for something different,
I wrote my own assembler which is available on here on github under the DiaperGlu repository.
This hello world code works with that assembler:
NEW-FLAT-OSYMBOL-BUF
X86-WORDLIST >SEARCH-ORDER
DECIMAL
OSYMBOL omyhelloworldmessage
$" Hello World!" PCURRENTCOMPILEBUFFER @ $ >BUF // pushes the message to the buffer
13 CODE-U8, 10 CODE-U8, // pushes crlf to the buffer
13 CODE-U8, 10 CODE-U8, // appends another crlf
13 CODE-U8, 10 CODE-U8, // and another crlf
OSYMBOL myhelloworldstart
// align the stack regardless of where it is when this function is called
HEX -10 N RSP AND,
1 N RDI MOV, // stdout handle
EH. omyhelloworldmessage [O] RSI LEA, // pmessageaddress
EH. myhelloworldstart EH. omyhelloworldmessage - N RDX MOV, // messagelength
IMP CALL, OSYMBOL-IMPORT write
IMP CALL, OSYMBOL-IMPORT exit
PCURRENTCOMPILEBUFFER @
EH
1 EH[ND]
BUF>NEWEXPORTIMPORT.OBUF
DUP$" helloworld64.o" SAVEFILE$
FREEBUFFER
SEARCH-ORDER> DROP
FREE-FLAT-OSYMBOL-BUF