汇编基础(2) -- ARM64

简介

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指令集更快。

  • 兼容性:ARM64架构与32位ARM架构不兼容,因此32位的应用程序不能在ARM64架构的处理器上直接运行。

寄存器

寄存器 说明
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

参考

你可能感兴趣的:(汇编,arm64)