简介
ARM架构中,ARM64(也称为AArch64)是一种64位处理器架构,它是ARMv8指令集的一部分。与之前的32位ARM架构相比,ARM64提供了更大的寄存器容量、更广阔的地址空间和更高的计算能力。
64位版本的指令集和32位版本的指令集有一些区别,这些区别主要涉及到以下几个方面:
-
寄存器:ARM64架构提供了31个通用寄存器,每个寄存器的容量为64位。相比之下,32位ARM架构只有16个通用寄存器,每个寄存器的容量为32位。
-
操作数大小:在ARM64架构中,所有数据都是以64位的形式进行处理。相比之下,32位ARM架构只能处理32位的整数和单精度浮点数。
-
内存地址空间:在ARM64架构中,虚拟地址空间最大可达256TB,可以同时支持多达4亿个进程。相比之下,32位ARM架构只支持最大4GB的虚拟地址空间,并且最多只能支持4096个进程。
-
执行速度:由于ARM64架构的寄存器容量更大、操作数更大,所以在大多数情况下,ARM64指令集的执行速度比32位ARM指令集更快。文章来源:https://www.toymoban.com/news/detail-730591.html
-
兼容性:ARM64架构与32位ARM架构不兼容,因此32位的应用程序不能在ARM64架构的处理器上直接运行。文章来源地址https://www.toymoban.com/news/detail-730591.html
寄存器
寄存器 | 说明 |
---|---|
x0-x7 | 通用寄存器,用于函数参数传递和返回值存储 |
x8 | 通用寄存器,可用作附加参数传递 |
x9-x15 | 通用寄存器,用于临时数据存储 |
x16 | 通用寄存器,可用作线程/进程本地数据存储区域指针 |
x17 | 通用寄存器,可用作异常链接寄存器 |
x18 | 通用寄存器,可用作平台相关寄存器 |
x19-x28 | 通用寄存器,用于临时数据存储 |
x29 (fp) | 帧指针寄存器,用于保存当前函数的帧指针 |
x30 (lr) | 链接寄存器,用于保存返回地址 |
sp | 栈指针寄存器,指向当前栈顶位置 |
pc | 程序计数器寄存器,存储下一条要执行的指令的地址 |
cpsr | 当前程序状态寄存器,保存处理器的当前状态信息,如条件标志位、中断使能位、处理模式等 |
nzcv | 零、负、进位和溢出条件标志位,记录上一条指令结果的状态 |
f0-f31 | 浮点寄存器,用于浮点运算 |
v0-v31 | 矢量寄存器,用于SIMD(单指令多数据)操作 |
w0 | 32位宽的低位部分,对应于x0寄存器 |
s0 | 16位宽的低位部分,对应于x0寄存器的低16位 |
b0 | 8位宽的最低字节部分,对应于x0寄存器的最低字节 |
指令
指令类型 | 示例指令 | 说明 |
---|---|---|
数据传输 | LDR X0, [X1] |
从内存中加载数据到寄存器 |
STR X0, [X1] |
将寄存器中的数据存储到内存 | |
算术运算 | ADD X0, X1, X2 |
将两个寄存器中的值相加 |
SUB X0, X1, X2 |
将两个寄存器中的值相减 | |
逻辑运算 | AND X0, X1, X2 |
将两个寄存器中的值进行按位与 |
ORR X0, X1, X2 |
将两个寄存器中的值进行按位或 | |
控制流 | B label |
分支到标签处执行 |
BL label |
分支并且保留返回地址 | |
CMP X0, X1 |
比较两个寄存器中的值 | |
BEQ label |
如果上一次比较结果为相等,则分支到标签处执行 | |
B label |
无条件跳转到标签处执行 | |
BL label |
分支与链接 跳转到标签处执行,并保存返回地址 | |
BR Xn |
无条件跳转到寄存器Xn中存储的地址 | |
B.cond label |
根据特定条件进行跳转 | |
BLR Xn |
无条件跳转到寄存器Xn中存储的地址,并保存返回地址 | |
BR Xn |
无条件跳转到寄存器Xn中存储的地址,并恢复返回地址及上下文 | |
BLR Xn |
跳转到寄存器Xn中存储的地址,并保存返回地址及上下文 | |
乘法和除法 | MUL X0, X1, X2 |
将两个寄存器中的值相乘 |
SDIV X0, X1, X2 |
将两个寄存器中的值相除 | |
浮点运算 | FADD D0, D1, D2 |
将两个浮点寄存器中的值相加 |
FSUB D0, D1, D2 |
将两个浮点寄存器中的值相减 | |
FMUL D0, D1, D2 |
将两个浮点寄存器中的值相乘 | |
FDIV D0, D1, D2 |
将两个浮点寄存器中的值相除 | |
压栈 | STP X0, X1, [SP, #-16]! |
将两个寄存器的值压入栈中 |
STR X0, [SP, #-8]! |
将一个寄存器的值压入栈中 | |
出栈 | LDP X0, X1, [SP], #16 |
从栈中弹出两个寄存器的值 |
LDR X0, [SP], #8 |
从栈中弹出一个寄存器的值 | |
设置栈指针 | MOV SP, X0 |
将指定寄存器的值设置为栈指针 |
获取栈指针 | MOV X0, SP |
将栈指针的值保存到指定寄存器 |
实例分析
- 包含if语法的函数:
int ifFunction(int x, int y) {
int result;
if (x > y) {
result = x + y;
} else {
result = x - y;
}
return result;
}
ifFunction:
cmp x0, x1 // 比较 x 和 y
ble else_label // 如果 x <= y,跳转到 else_label 标签处
add x0, x0, x1 // 如果 x > y,执行 x + y
ret // 返回结果
else_label:
sub x0, x0, x1 // 如果 x <= y,执行 x - y
ret // 返回结果
- 包含for语法的函数:
int forFunction(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
forFunction:
mov w1, 1 // 将 1 赋值给寄存器 w1,作为循环计数器 i 的初始值
mov w0, 0 // 将 0 赋值给寄存器 w0,作为累加和 sum 的初始值
loop:
add w0, w0, w1 // 累加计数器 i 的值到累加和 sum
add w1, w1, 1 // 计数器 i 自增 1
cmp w1, x0 // 比较计数器 i 和 n 的值
ble loop // 如果 i <= n,跳转到 loop 标签处继续循环
ret // 返回累加和 sum
- 包含switch语法的函数:
int switchFunction(int x) {
int result;
switch (x) {
case 1:
result = 10;
break;
case 2:
result = 20;
break;
case 3:
result = 30;
break;
default:
result = -1;
}
return result;
}
switchFunction:
cmp w0, 1 // 比较寄存器 w0(x)的值与每个 case 的值
b.eq case_1 // 如果相等,跳转到 case_1 标签处
cmp w0, 2
b.eq case_2
cmp w0, 3
b.eq case_3
mov w0, -1 // 默认情况下,将 -1 赋值给寄存器 w0(result)
ret
case_1:
mov w0, 10 // 如果 x == 1,将 10 赋值给寄存器 w0(result)
ret
case_2:
mov w0, 20 // 如果 x == 2,将 20 赋值给寄存器 w0(result)
ret
case_3:
mov w0, 30 // 如果 x == 3,将 30 赋值给寄存器 w0(result)
ret
参考
到了这里,关于汇编基础(2) -- ARM64的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!