Search code examples
macosgccassemblynasm

How can I run this assembly code on OS X?


Starting to learn assembly, I was given some Hello World assembly code created during the class on Linux. I would like to get it to work for 64-bit Mac OS X.

code.asm:

SECTION .data       
    hola:   db "Hola!",10   
    tam:    equ $-hola      

SECTION .text       
    global main     

main:               

    mov edx,tam     
    mov ecx,hola        
    mov ebx,1       
    mov eax,4       
    int 0x80        

    mov ebx,0       
    mov eax,1       
    int 0x80        

This is what I do:

nasm -f macho32 -o object.o code.asm
gcc -m32 -o program object.o

Which tells me:

Undefined symbols for architecture i386: "_main", referenced from: start in crt1.10.6.o ld: symbol(s) not found for architecture i386

Searching for this error, I found this question: nasm and gcc: 32 bit linking failed (64 bit Mac OS X)

One answer says

The problem you're having is that you're creating a 32-bit Linux(ELF) object file which isn't compatible with the Mac OS X object format. Try switching '-f elf' to '-f macho32'.

But I'm definitely using -f macho32. So what would the problem be then?


Solution

  • 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...

    1. 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).
    2. nasm doesn't come with the macho64 output type installed by default
    3. 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