Reputation: 317
I'm trying to learn a little bit of assembly, so I've been following the most basic tutorial I can find that takes into account differences between macOS and linux-based OSs. I'm running macOS Catalina 10.15.1.
Unfortunately, I can't get the examples to link. Following along with this answer, I was able to link the basic hello.asm
by adding the -lSystem
flag to ld
, i.e., I saved as hello.asm
the following code
; ----------------------------------------------------------------------------------------
; Writes "Hello, World" to the console using only system calls. Runs on 64-bit macOS only.
; To assemble and run:
;
; nasm -fmacho64 hello.asm && ld hello.o && ./a.out
; ----------------------------------------------------------------------------------------
global start
section .text
start: mov rax, 0x02000004 ; system call for write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, message ; address of string to output
mov rdx, 13 ; number of bytes
syscall ; invoke operating system to do the write
mov rax, 0x02000001 ; system call for exit
xor rdi, rdi ; exit code 0
syscall ; invoke operating system to exit
section .data
message: db "Hello, World", 10 ; note the newline at the end
and instead of running the given linking / execution commands, ran
nasm -f macho64 hello.asm && ld -lSystem hello.o && ./a.out
and it successfully linked and wrote Hello, World
to stdout
.
However, when I move onto the second example,
; ----------------------------------------------------------------------------------------
; This is an OSX console program that writes a little triangle of asterisks to standard
; output. Runs on macOS only.
;
; nasm -fmacho64 triangle.asm && gcc hola.o && ./a.out
; ----------------------------------------------------------------------------------------
global start
section .text
start:
mov rdx, output ; rdx holds address of next byte to write
mov r8, 1 ; initial line length
mov r9, 0 ; number of stars written on line so far
line:
mov byte [rdx], '*' ; write single star
inc rdx ; advance pointer to next cell to write
inc r9 ; "count" number so far on line
cmp r9, r8 ; did we reach the number of stars for this line?
jne line ; not yet, keep writing on this line
lineDone:
mov byte [rdx], 10 ; write a new line char
inc rdx ; and move pointer to where next char goes
inc r8 ; next line will be one char longer
mov r9, 0 ; reset count of stars written on this line
cmp r8, maxlines ; wait, did we already finish the last line?
jng line ; if not, begin writing this line
done:
mov rax, 0x02000004 ; system call for write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, output ; address of string to output
mov rdx, dataSize ; number of bytes
syscall ; invoke operating system to do the write
mov rax, 0x02000001 ; system call for exit
xor rdi, rdi ; exit code 0
syscall ; invoke operating system to exit
section .bss
maxlines equ 8
dataSize equ 44
output: resb dataSize
I get an error from ld. (Note the typo in the bash command given. I actually tried nasm -f macho64 triangle.asm && ld -lSystem triangle.o && ./a.out
.) The message is:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
This is the same error as when I link the first example without the -lSystem
flag; however, here adding the -lSystem
flag does not solve the problem.
At the most concert level, what emendations do I have to make to triangle.asm
or the command I'm using to link it to solve this "undefined symbols" error? At a more general level, why am I getting this error at all? The symbol _main
doesn't appear anywhere in my code. Does my object file actually get "wrapped" in something else by the linker to create a runnable executable? If so, is this a necessary default? Why can't the processor effectively just run these instructions from top to bottom? I would have assumed that this code is sufficiently low-level that it can be run without linking to any additional libraries.
Upvotes: 3
Views: 1736
Reputation: 31
Just ld -o tri tri.o -static
seems to do the job as well. Looks like the missing ingredient was -static
parameter.
Upvotes: 3
Reputation: 31
Already tested in macOS 10.15.
% nasm -f macho64 -o tri.o triangle.asm
% ld -o tri -e start tri.o -macosx_version_min 10.15 -static
% ./tri
output: enter image description here
Upvotes: 3