I want to learn assembly, and I figured that compiling C code to assembly would be a good start. That is to say: cc main.c -S
which compiles
#include <stdio.h>
int main() {
printf("Hello, World!\n");
}
to
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 14, 0 sdk_version 14, 5
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
.cfi_def_cfa_offset 16
mov x29, sp
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
adrp x0, l_.str@PAGE
add x0, x0, l_.str@PAGEOFF
bl _printf
mov w0, #0
ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
ret
.cfi_endproc
; -- End function
.section __TEXT,__cstring,cstring_literals
l_.str: ; @.str
.asciz "Hello, World!\n"
.subsections_via_symbols
... As you can see, I'm running on aarch64. But that is not the problem:
as main.s
still no problem. But when I do ld a.out
:
Undefined symbols for architecture arm64:
"_printf", referenced from:
_main in a.out
ld: symbol(s) not found for architecture arm64
Now, I already found a solution for this on some obscure, almost completely unrelated blog post, so:
ld a.out -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/ -lSystem
and now it works.
$ ./a.out
Hello, World!
So here the question: how am I supposed to know how _printf is defined? I mean, I already know how to do a syscall
and write to stdout
, but for anything more complicated, this will become such a chore. The whole point of this is for me to learn Assembly, but dynamic linking is making this very difficult. If I could statically link it, it would make things so much easier. Is there a compiler that allows this? By the way, I'm using clang:
$ cc --version
Apple clang version 15.0.0 (clang-1500.3.9.4)
Target: arm64-apple-darwin23.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
I tried as follows:
$ cc main.c -static
ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
and
$ cc main.c -lstatic
ld: library 'static' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)
and
$ cc main.c -static -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/
ld: library not found for -lcrt0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
and when I do
$ cc main.c -static -S
-static
is just being ignored.
I tried a lot of other things; some I don't don't remember, some I can't be bothered to write down. You get the gist of it. Please help.
You can disassemble a static object file by doing this:
gcc -march=native -static main.c -o main.o
objdump -drwC -Mintel main.o > main.s