Thursday, July 28, 2022

[SOLVED] How can I run this assembly code on OS X?

Issue

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



Answered By - Benjamin Dean
Answer Checked By - Willingham (WPSolving Volunteer)