写个最简单的helloword.c方法,使用clang
命令编译
#include
int main() {
printf("hellow word\n");
return 0;
}
使用clang -S -arch arm64 -isysroot
xcrun --sdk iphoneos --show-sdk-pathhelloword.c
, 其中xcrun --sdk iphoneos --show-sdk-path
输出响应版本sdk
的目录
.section __TEXT,__text,regular,pure_instructions
.build_version ios, 13, 4 sdk_version 13, 4
.globl _main ; -- Begin function main
.p2align 2
_main: ; @main
.cfi_startproc
; %bb.0:
sub sp, sp, #32 ; =32
stp x29, x30, [sp, #16] ; 16-byte Folded Spill
add x29, sp, #16 ; =16
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
stur wzr, [x29, #-4]
adrp x0, l_.str@PAGE
add x0, x0, l_.str@PAGEOFF
bl _printf
mov w8, #0
str w0, [sp, #8] ; 4-byte Folded Spill
mov x0, x8
ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
add sp, sp, #32 ; =32
ret
.cfi_endproc
; -- End function
.section __TEXT,__cstring,cstring_literals
l_.str: ; @.str
.asciz "hellow word\n"
.subsections_via_symbols
代码中类似.section或.globl等以'.'开头的, 被称之为编译器指令
类似_main:
或l_.str:
被称之为标签(label), 用于辅助定位代码或者资源地址
类似pushq或movq的, 被称之为汇编指令, 它们会被汇编器编译为机器代码, 最终被cpu所执行
基本汇编知识
寄存器
寄存器是CPU中的高速存储单元,要比内存中存取要快的多。
r0~r30
r0 - r30
是31个通用整形寄存器。每个寄存器可以存取一个64位大小的数。 当使用 x0 - x30
访问时,它就是一个64位的数。当使用w0 - w30
访问时,访问的是这些寄存器的低32位
其中
r29
又被叫做 fp
(frame pointer
). r30
又被叫做 lr
(link register
)
SP
SP
寄存器其实就是 x31
,在指令编码中,使用 SP/WSP
来进行对SP
寄存器的访问
V0 – V31
V0 - V31
是向量寄存器,也可以说是浮点型寄存器。它的特点是每个寄存器的大小是 128 位的。 分别可以用Bn Hn Sn Dn Qn
的方式来访问不同的位数。如图
SPRs
SPRs是状态寄存器,用于存放程序运行中一些状态标识。不同于编程语言里面的if else.在汇编中就需要根据状态寄存器中的一些状态来控制分支的执行。状态寄存器又分为 The Current Program Status Register (CPSR)
和 The Saved Program Status Registers (SPSRs)
。 一般都是使用CPSR
, 当发生异常时, CPSR
会存入SPSR
。当异常恢复,再拷贝回CPSR
。
还有一些系统寄存器,还有 FPSR FPCR
是浮点型运算时的状态寄存器等。基本了解上面这些寄存器就可以了
栈
栈就是指令执行时存放临时变量的内存空间。在学习汇编代码的执行过程中,了解栈的结构非常重要。
先列出一些栈的特性:
- 栈是从高地址到低地址的, 栈低是高地址,栈顶是低地址。
- fp指向当前frame的栈底,也就是高地址。
-
sp指向栈顶,也就是地地址。
下面的图简单的描述了从方法A调用方法B时 栈是如何划分的: