I've been trying to teach myself some entry-level Assembly programming too, and I ran into similar issues. I had originally compiled using nasm
with elf
, but that didn't work when I tried to use ld
to link the object file and create the executable.
I think the answer you main question "what would the problem be then?" [to get this to run on 64bit MacOSX]
is: You are using -f macho32
but expecting it to run on a 64bit machine, you need to change the command option to be -f macho64
. Of course, this will not resolve the fact that your assembly code is written for a different architecture (more on that in a bit).
I found this handy answer on the right command to use in this instance to compile and link your code (after you refactor your assembly code to use the proper syntax instead of *nix as duskwuff stated): nasm -f macho64 main.asm -o main.o && ld -e _main -macosx_version_min 10.8 -arch x86_64 main.o -lSystem
After some searching, here's what I learned...
- On Mac 64bit, it might be better to use the
as
assembler instead of nasm
(if you want something more native), but if you want more portable code (learn the differences).
nasm
doesn't come with the macho64 output type installed by default
- Assembly is a pain in the keister (this aside)
Now that my learning rant is out of the way...
Here is the code which should operate on MacOSX 64 using nasm
(if you have updated nasm
with macho64
, credit to Dustin Schultz):
section .data
hello_world db "Hello World!", 0x0a
section .text
global start
start:
mov rax, 0x2000004 ; System call write = 4
mov rdi, 1 ; Write to standard out = 1
mov rsi, hello_world ; The address of hello_world string
mov rdx, 14 ; The size to write
syscall ; Invoke the kernel
mov rax, 0x2000001 ; System call number for exit = 1
mov rdi, 0 ; Exit success = 0
syscall ; Invoke the kernel
Working code I used with the as
assembler native to MacOSX64:
.section __TEXT,__text
.global start
start:
movl $0x2000004, %eax # Preparing syscall 4
movl $1, %edi # stdout file descriptor = 1
movq str@GOTPCREL(%rip), %rsi # The string to print
movq $100, %rdx # The size of the value to print
syscall
movl $0, %ebx
movl $0x2000001, %eax # exit 0
syscall
.section __DATA,__data
str:
.asciz "Hello World!\n"
Compile command: as -arch x86_64 -o hello_as_64.o hello_as_64.asm
Link Command: ld -o hello_as_64 hello_as_64.o
Execute Command: ./hello_as_64
Some helpful resources I found along my journey:
AS
OSX Assembler Reference: https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/Assembler/Assembler.pdf
Writing 64 Bit Assembly on Mac OSX: http://www.idryman.org/blog/2014/12/02/writing-64-bit-assembly-on-mac-os-x/
Couldn't link object file using ld
:
Can't link object file using ld - Mac OS X
OSX i386 SysCalls: http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/mach/i386/syscall_sw.h
OSX Master System Call Definitions: http://www.opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master
OSX Syscall: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/syscall.2.html