我想学习汇编,我认为将 C 代码编译为汇编将是一个好的开始。也就是说:
cc main.c -S
编译
#include <stdio.h>
int main() {
printf("Hello, World!\n");
}
到
.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
...如您所见,我在 aarch64 上运行。但这不是问题:
as main.s
还是没问题。但是当我这样做时ld a.out
:
Undefined symbols for architecture arm64:
"_printf", referenced from:
_main in a.out
ld: symbol(s) not found for architecture arm64
现在,我已经在一些晦涩难懂、几乎完全不相关的博客文章上找到了解决方案,所以:
ld a.out -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/ -lSystem
现在可以了。
$ ./a.out
Hello, World!
所以这里的问题是:我应该如何知道 _printf 是如何定义的?我的意思是,我已经知道如何做
syscall
并写信给 stdout
,但对于任何更复杂的事情,这将变得非常繁琐。这对我来说是为了学习汇编,但动态链接使这变得非常困难。如果我可以静态链接它,事情就会变得容易得多。有没有允许这样做的编译器?顺便说一句,我正在使用 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
我尝试如下:
$ 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)
和
$ cc main.c -lstatic
ld: library 'static' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)
和
$ 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)
当我这样做时
$ cc main.c -static -S
-static
只是被忽略了。
我尝试了很多其他的事情;有些我不记得了,有些我懒得写下来。你明白了它的要点。请帮忙。
您可以通过执行以下操作来反汇编静态目标文件:
gcc -march=native -static main.c -o main.o
objdump -drwC -Mintel main.o > main.s