How to compile using nasm on MacOSX
Asked Answered
A

4

14

I am trying to compile and link my first program on Assembler. I try to compile the following code:

; %include "stud_io.inc"    
global _main     

section .text
_main: 
    xor eax, eax
again:
    ; PRINT "Hello"
    ; PUTCHAR 10
    inc eax     
    cmp eax, 5
    jl again

Below the console command for compiling and linking a program:

-bash-3.2$ nasm -f macho main.asm -o main.o  && ld -e _main -macosx_version_min 10.8 -arch x86_64 main.o

But the result is:

ld: warning: ignoring file main.o, file was built for i386 which is not the architecture being linked (x86_64): main.o
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     -u command line option
ld: symbol(s) not found for architecture x86_64

I think its necessary to compile the main.asm file for x86_64.. How to compile programs for my system properly?

Ace answered 31/12, 2012 at 16:0 Comment(4)
nasm does not recognize this optionAce
what version of nasm are you running?Robinette
-bash-3.2$ nasm -v NASM version 0.98.40 (Apple Computer, Inc. build 11) compiled on Aug 4 2012Ace
That version of nasm is very outdated. Look at nasm.us/pub/nasm/releasebuilds/2.10Monocular
M
18

I would recommend first updating your NASM.

After that, try running this:

nasm -f macho64 main.asm -o main.o  && ld -e _main -macosx_version_min 10.8 -arch x86_64 main.o -lSystem

Notice that the new command adds JasonD's suggestion above (macho64), but also adds the -lSystem to the ld command to stop ld from throwing following error:

ld: dynamic main executables must link with libSystem.dylib for architecture x86_64
Monocular answered 31/12, 2012 at 16:26 Comment(2)
The segfault is a problem with the code execution. After the jl instruction, add a ret instruction (since you are using a main). Note that if you are using pure x86 assembly, you need to exit by using the exit system call in int 0x80 (but not in this case). Remember that the PC counter needs to know where to go to continue execution when your code is done.Monocular
ld -lSystem my.o -e _main -macosx_version_min 10.14 -o exit Result - > cannot execute binary fileFriedland
L
1

I noticed that most examples show standalone assembly programs, but it is perhaps more common for assembly to be called from C. I created a simple C program that uses a minimal nasm-assembled function like this:

extern unsigned cpuid(unsigned n);

/* ... */
        unsigned n = cpuid(1);

The assembly looks like this:

section .text
    global _cpuid

_cpuid:
    push rbp
    mov rbp, rsp
    mov rax, rdi
    cpuid
    mov rax, rcx
    leave
    ret

You can see the whole thing, including nasm CLI options in the makefile, here:

https://github.com/ecashin/low/tree/master/cpuid

It does something mildly useful by printing out the availability of some CPU-specific features. (But it does that by using CPUID without checking whether it's available. If the CPU is Intel and newer than an i486, though, that's fine.)

The example is tested on Mac OS X Snow Leopard with the nasm from the ports collection. Removing the underscore prefix is the only change necessary for porting to Linux x86_64.

Lilas answered 1/9, 2013 at 20:45 Comment(2)
Also, I did need to update NASM as the other comments here say before I could use -fmacho64.Lilas
Your function violates the calling convention, overwriting the caller's RBX. You should push/pop it instead of RBP which you don't use. Also, normally you should just use <cpuid.h> assuming Apple Clang provides one that's similar to GCC's with __get_cpuid. How do I call "cpuid" in Linux? (It's not actually Linux-specific, although maybe GCC-specific.)Torpid
T
0

maybe try static linking?

ld -macosx_version_min 10.13 -e _main -static main.o
Turbidimeter answered 25/5, 2020 at 4:38 Comment(0)
M
0

You need to write it it for the AArm64 architecture and the compile it using gcc. Here is my simple program that just exist with system code 1 :

// main.s

.global _start
_start:
   mov x0, 1             // Set exit status 1 in x0.
   mov x8, 93            // System call number for exit in ARM64.
   svc 0                 // Invoke system call.

Compile with :

gcc -o main  main.s 

run

./main

Verify the exit code of application to make sure it existed with code 1 we set in assembly code:

echo $?
``
Mertz answered 3/3, 2024 at 1:45 Comment(1)
That's not NASM syntax, that's GAS. NASM is an x86 assembler only, no support for other architectures like AArch64 (aka ARM64). This doesn't answer the question, it's not asking how to write assembly on any Mac, it's asking for x86-64 NASM. Perhaps a link in a comment to a question about assembly on AArch64 Macs would be appropriate, but I don't think an answer is. (If there isn't an existing question with an answer like this or where this would work as an answer, you could post a new self-answered one.)Torpid

© 2022 - 2025 — McMap. All rights reserved.