一、简介
ARM64(也称为ARMv8-A架构)是ARM处理器的64位版本,广泛用于移动设备、服务器和嵌入式系统。苹果的 iPhone 设备从 5s( 2013 年 9 月)开始支持ARM64。
二、寄存器
1、通用寄存器 x0~x30, 可以存储整数,指针和其他数据。具体详情如下:
| x0~x7 | 通常用于传递函数参数和返回值 |
|---|---|
| x8 | 有时被称为间接结果寄存器,通常用于返回结构体之类的大数据 |
| x29(FP) | 帧指针(FP),在标准调用约定中用于指向当前堆栈帧。 |
| x30(LR) | 链接寄存器(LR),用于存储子程序返回地址 |
2、SP: 用于指向当前方法栈的顶部
3、PC: 总是指向即将要执行的下一条指令
4、状态寄存器(CPSR) :用于存放运算,主要是要了解NZCV这四位
| N | 运算结果为负数 |
|---|---|
| Z | 运算结果为零 |
| C | 运算结果产生了进位或借位 |
| V | 运算结果产生了溢出 |
三、指令
1、运算指令
1.1、add
用于执行加法运算。它可以将两个寄存器的值相加,或者将寄存器的值和一个立即数相加
//将 x0和 x1 的值相加存放到 x2中add x2 x0 x1 //将 x1 和整数 10相加存放d到 x0 中add x0 x1 #10
1.2、sub
用于执行减法法运算。与加法操作类似
//x2 = x0 - x1sub x2 x0 x1 //x0 = x1 - 10sub x0 x1 #10
1.3、mul
用于两个数相乘
//x2 = x0 * x1mul x2 x0 x1 //x0 = x1 * 10mul x0 x1 #10
2、加载存储指令
2.1、mov
用于将一个值(立即数或另一个寄存器的值)复制到目标寄存器中。
//将一个立即数加载到寄存器 x0mov x0 #1234//将x0的值复制到 x1 中mov x1 x0
2.2、ldr
用于从内存加载数据到寄存器,有众多的变体,例如:如ldr, ldrb, ldrh, ldrsw等。
// 从内存地址(x1 + 8)处加载数据到寄存器x0ldr x0, [x1, #8]// 从内存地址(x1 + x2)处加载数据到寄存器x0ldr x0, [x1, x2]
2.3、str
用于将寄存器中的数据存储到内存中。类似于ldr指令,str指令也有多种变种,用于不同大小和类型的数据存储。
//将寄存器x0中的数据存储到内存地址(x1 + 8)处str x0, [x1, #8]//将寄存器x0中的数据存储到内存地址(x1 + x2)处str x0, [x1, x2]
3、比较指令
3.1、cmp
用于比较两个寄存器的值。它实际上执行一个隐式的减法运算,不存储结果,只更新条件标志(flags)。这些标志(N, Z, C, V)可用于后续的条件分支指令,以决定程序的执行路径。经常与跳转指令搭配使用,例如 b.eq、b.lt、b.gt。
.global _start_start: mov x0, #5 // 将 5 加载到寄存器 x0 mov x1, #10 // 将 10 加载到寄存器 x1 cmp x0, x1 // 比较寄存器 x0 和 x1 的值 b.eq equal_case // 如果 x0 == x1,跳转到 equal_case b.lt less_case // 如果 x0 < x1,跳转到 less_case b.gt greater_case // 如果 x0 > x1,跳转到 greater_caseequal_case: // x0 和 x1 相等的情况下执行的代码 b endless_case: // x0 小于 x1 的情况下执行的代码 b endgreater_case: // x0 大于 x1 的情况下执行的代码end: // 程序结束 mov x8, #93 // 系统调用号(sys_exit) mov x0, #0 // 退出状态码 svc #0 // 触发系统调用
4、跳转指令
4.1、b
用于无条件跳转到指定的标签,常与相关的比较指令搭配使用。
b.eq <label> // 如果相等(Z = 1),跳转到标签 <label>b.ne <label> // 如果不相等(Z = 0),跳转到标签 <label>b.lt <label> // 如果小于(N ≠ V),跳转到标签 <label>b.le <label> // 如果小于或等于(Z = 1 或 N ≠ V),跳转到标签 <label>b.gt <label> // 如果大于(Z = 0 且 N = V),跳转到标签 <label>b.ge <label> // 如果大于或等于(N = V),跳转到标签 <label>