ARM是什么?
- ARM处理器是英国Acorn有限公司设计的低功耗成本的微处理器。全称为Advanced RISC Machine。ARM处理器本身是32位设计,但也配备16位指令集,一般来讲比等价32位代码节省达35%,却能保留32位系统的所有优势。
- ARM通俗来说是一类小型处理器(CPU),例如各类手机,平板电脑的处理器.
- iphone采用的是苹果的A系处理器.
iOS 中的 armv7,armv7s,arm64,i386,x86_64 这些都代表什么?
armv7|armv7s|arm64都是ARM处理器的指令集
i386|x86_64 是Mac处理器的指令集
arm64:iPhone5s 以后的机型
armv7s:iPhone5|iPhone5C
armv7:iPhone4|iPhone4S
i386是针对intel通用微处理器32位处理器
x86_64是针对x86架构的64位处理器
模拟器32位处理器测试需要i386架构,
模拟器64位处理器测试需要x86_64架构,
真机32位处理器需要armv7,或者armv7s架构,
真机64位处理器需要arm64架构。
Xcode中的配置参数说明:
- Architectures
指定了工程被编译成支持哪些指令集类型,支持的指令集越多,就会编译出多个指令集代码的数据包,以便运行于不同cpu架构的设备上,对应生成二进制包就越大,也就是ipa包越大。指令集会打包到mach-o文件中,打包多个指令集,mach-o文件中会看到有多个.o文件.
- Valid Architectures
限制可能被支持指令集的范围,就是xcode编译出来的二进制包类型最终从这些类型产生,而编译出哪些指令集的包,将由Architectures与Valid Architectures这些交集来确定。
- Build Active Architecture Only
指定是都只对当前连接设备所支持的指令集编译,当设置为YES时,是为了debug编译的速度更快,它只会编译当前的architecture版本,当设置为NO时,会编译所有的版本,所以一般debug设置为YES,release设置为NO,以适应不同设备。
- 使用 standard architectures (including 64-bit)(armv7,arm64) 参数,则打的包里面有32位、64位两份代码,在iPhone5s以上的机型( iPhone5s的cpu是64位的 )下,会首选运行64位代码包, 其余的iPhone( 其余iPhone都是32位的,iPhone5c也是32位 ),只能运行32位包。
- 而使用 standard architectures (armv7,armv7s) 参数, 则打的包里只有32位代码, iPhone5s的cpu是64位,但是可以兼容32位代码,即可以运行32位代码。但是这会降低iPhone5s的性能。 其余的iPhone对32位代码包更没问题, 而32位代码包,对系统也几乎也没什么限制。
CPU&寄存器
内部部件之间由总线连接,寄存器的作用就是进行数据的临时存储.
- cpu除了有控制器、运算器还有寄存器。其中寄存器的主要作用是进行数据的临时存储。
cpu的运算速度非常快,为了匹配性能,在cpu内部设计了一快临时存储区域,称为寄存器.在进行运算时先将数据从内存复制到寄存器然后再寄存器完成计算.
- 对程序员来说,CPU中最主要部件是寄存器,可以通过改变寄存器的内容来实现对CPU的控制
对于arm系的cpu来说,如果寄存器一x开头表明这是一个64位寄存器.如果是一w开头则表明是一个32位的寄存器,在系统中没有16位和8位的寄存器提供使用.并且32位的寄存器是64位寄存器的低32位,而不是独立存在的.这样做的目的就是避免运算浪费,节省空间,提升运算速度.
- 不同的CPU,寄存器的个数、结构是不相同的
寄存器概念(摘自百科)
寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,寄存器有累加器(ACC)。
注意:ARM64架构的cpu中并没有累加器的概念.
寄存器分类
通用寄存器、浮点寄存器、向量寄存器(图像领域)、标志寄存器等
- ARM64 有34个寄存器,包括31个通用寄存器、SP、PC、CPSR**
通用寄存器:x0 到 x30
浮点寄存器:64位D0~D31 32位S0~S31
向量寄存器:128位 V0~V31 应用于图形图像处理领域
1. 通用寄存器(x0 到 x30)
x0 到 x30这些寄存器通常用来存放一般性的数据,称为通用寄存器(有时也有特定用途x29,x30).w0~w28(通用寄存器低32位,注意:没有w29和w30,x29,x30不可以拆开来用)
x29(fp)64位 栈指针寄存器
x30(lr) 64位 通常称X30为程序链接寄存器,保存子程序结束后需要执行的下一条指令
通常,CPU会先将内存中的数据存储到通用寄存器中,然后再对通用寄存器中的数据进行运算
-
假设内存中有块红色内存空间的值是3,现在想把它的值加1,并将结果存储到蓝色内存空间
CPU首先会将红色内存空间的值放到X0寄存器中:mov X0,红色内存空间
然后让X0寄存器与1相加:add X0,1
最后将值赋值给内存空间:mov 蓝色内存空间,X0
2. SP 堆栈指针寄存器,使用 SP/WSP来进行对SP寄存器的访问。
3. PC 指令指针寄存器(program counter),俗称PC指针.
它指示了当前cpu将要读取指令的地址(即将执行的地址,即下一条指令)
4. CPSR 64位 状态寄存器(Current Program Status Register )
CPSR是状态寄存器,用于存放程序运行中一些状态标识。其他寄存器是用来存放数据的,而CPSR寄存器是按位起作用的,它的每一位都有专门的含义.不同于编程语言里面的if else.在汇编中就需要根据状态寄存器中的一些状态来控制分支的执行。
NZCV是状态寄存器的条件标志位,分别代表运算过程中产生的状态,其中:
N, negative condition flag,一般代表运算结果是负数
Z, zero condition flag, 指令结果为0时Z=1,否则Z=0;
C, carry condition flag, 无符号运算有溢出时,C=1。
V, oVerflow condition flag 有符号运算有溢出时,V=1。
指令
- ARM64经常用到的汇编指令
MOV X1,X0 ;将寄存器X0的值传送到寄存器X1
ADD X0,X1,X2 ;寄存器X1和X2的值相加后传送到X0
SUB X0,X1,X2 ;寄存器X1和X2的值相减后传送到X0
AND X0,X0,#0xF ; X0的值与0xF相位与后的值传送到X0
ORR X0,X0,#9 ; X0的值与9相位或后的值传送到X0
EOR X0,X0,#0xF ; X0的值与0xF相异或后的值传送到X0
LDR X5,[X6,#0x08] ;X6寄存器加0x08的和的地址值内的数据传送到X5
STR X0, [SP, #0x8] ;X0寄存器的数据传送到SP+0x8地址值指向的存储空间
STP x29, x30, [sp, #0x10] ;入栈指令
LDP x29, x30, [sp, #0x10] ;出栈指令
CBZ ;比较(Compare),如果结果为零(Zero)就转移(只能跳到后面的指令)
CBNZ ;比较,如果结果非零(Non Zero)就转移(只能跳到后面的指令)
CMP ;比较指令,相当于SUBS,影响程序状态寄存器CPSR
B/BL ;绝对跳转#imm, 返回地址保存到LR(X30)
RET ;子程序返回指令,返回地址默认保存在LR(X30)
其中 MOV
指令只能用于寄存器之间传值,寄存器和内存之间传值通过 LDR
和 STR
-
ARM指令又一个重要特点就是所有指令都是带有条件的,就是说汇编中就需要根据状态寄存器中的一些状态来控制分支的执行。例如:
图中指令
b
是跳转指令,后边跟着跳转的条件eq
,那么这个eq
是什么意思呢? -
ARM指令的结构
上图列出了不同种类ARM指令的编码格式,文章开头讲过ARM指令长度固定为 32bit即图中的0-31位。
28-31位是条件码,21-24为操作码,12-19为寄存器编号
上边提到的跳转条件eq
实际就是28-31位对应的条件码,但是28-31位都是二进制数据不好记,所以就对二进制的条件码取了好记的助记符,例如 eq
。
eq
英文单词equal
的意思,注意这里equal
并不是c语言当中==
的意思,这里根据状态寄存器的条件标志位Z
来判断,如果Z = 1
则eq
成立,如果Z = 0
则eq
不成立,就是NE
。
- ARM指令包含4位的条件码列表:
操作码 | 条件码助记符 | 标志 | 含义 |
---|---|---|---|
0000 | EQ | Z=1 | 相等 |
0001 | NE(Not Equal) | Z=0 | 不相等 |
0010 | CS/HS(Carry Set/High or Same) | C=1 | 无符号数大于或等于 |
0011 | CC/LO(Carry Clear/LOwer) | C=0 | 无符号数小于 |
0100 | MI(MInus) | N=1 | 负数 |
0101 | PL(PLus) | N=0 | 正数或零 |
0110 | VS(oVerflow set) | V=1 | 溢出 |
0111 | VC(oVerflow clear) | V=0 | 没有溢出 |
1000 | HI(HIgh) | C=1,Z=0 | 无符号数大于 |
1001 | LS(Lower or Same) | C=0,Z=1 | 无符号数小于或等于 |
1010 | GE(Greater or Equal) | N=V | 有符号数大于或等于 |
1011 | LT(Less Than) | N!=V | 有符号数小于 |
1100 | GT(Greater Than) | Z=0,N=V | 有符号数大于 |
1101 | LE(Less or Equal) | Z=1,N!=V | 有符号数小于或等于 |
1110 | AL | 任何 | 无条件执行(默认) |
1111 | NV | 任何 | 从不执行 |
ARM指令所有指令都是带有条件的,默认是AL
即无条件执行,当指令带有默认条件时不需要明确写出。
参考:
https://blog.cnbluebox.com/blog/2017/07/24/arm64-start/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
https://blog.csdn.net/lizhongfu2013/article/details/42387311
https://www.jianshu.com/p/797b9e15f87c
https://www.jianshu.com/p/2f4a5f74ac7a