首页
社区
课程
招聘
[原创]ARM架构笔记
发表于: 6天前 353

[原创]ARM架构笔记

6天前
353

ARMv7 ​​aarch32 ARM32

  • armv7: ARM 第 7 代 32 位处理器架构规范(2004年发布), 仅支持 32 位指令集(A32/T32)
  • ​​aarch32​: ​​不专属于 ARMv7​​, 而是 ARMv8 架构定义的 ​​32 位执行状态​​, ​​兼容 ARMv7 指令集​​并扩展新功能(如加密指令、LPAE)。
  • ARM32: 非官方术语, 通常泛指​​所有32位 ARM 架构​​(包括 ARMv7 及更早版本), 在 Android 系统中特指 armeabi-v7a。

ARMv8 ​​aarch64 ARM64

  • ARMv8: ARM 第 8 代架构(2011年发布), 首次引入 ​​64 位支持​​, 同时兼容 32 位(AArch32)
  • ​​aarch64: ARMv8 架构中 ​​64 位执行状态的官方名称​​, 支持 A64 指令集和 64 位寄存器(X0-X30)。
  • ARM64: AArch64 的行业别名​​, 在Linux/Android 系统中广泛使用(如arm64-v8a)。

ARM64 寄存器

  • ​​X 寄存器​: 64位通用寄存器, 用于处理64位数据或地址(例如 X0~X30)
  • W 寄存器​: 32位寄存器, 对应 X 寄存器的​​低32位​​(例如 W0 是 X0 的低32位), 写入 W 寄存器时, 会将对应 X 寄存器的高32位清零(例如写入 W0=0xFFFFFFFF 后 X0=0x00000000FFFFFFFF)
    • X0-X7: 用于参数传递, 注意 X0, X1 可用于储存函数结果, 大小 ≤ 8字节: 整个返回值由 x0 容纳, 大小 ≤ 16字节: 低8字节存 x0, 高8字节存 x1
    • X9-X15: 在子函数中使用这些寄存器时, 直接使用即可, 无需save/restore. 在汇编代码中x9-x15出现的频率极低
    • X19-X29: 在callee子函数中使用这些寄存器时, 需要先save这些寄存器, 在退出子函数时再resotre
    • X8, X16-X18, X29, X30 这些都是特殊用途的寄存器
      • X8: 作为间接结果位置寄存器​​, 当函数返回​​大于 16 字节的结构体​​时,调用方预先分配内存并将地址存入 X8
      • X16、X17: 进程内临时寄存器
      • X18: 保留用于ABI
      • X29: FP(frame pointer register, 帧指针寄存器)FP 指向当前函数栈帧的起始位置(栈底), 用于界定函数的栈空间范围。在函数调用链中, FP 形成“链表式”结构, 每个栈帧保存上一级函数的 FP 值, 实现栈回溯(backtrace)
      • X30: LR(Link Register, 链接寄存器)​保存返回地址​​, 当执行 BL(Branch with Link)或 BLX 指令调用子函数时, LR 自动存储​​下一条指令的地址​​, 确保函数返回后继续执行正确位置
  • V 寄存器​: 128 位浮点/向量寄存器, 共有 32 个(V0~V31), V0–V31 构成了完整的浮点与 SIMD(单指令多数据)运算寄存器组, 这些寄存器支持浮点运算、SIMD 并行计算(如图形处理)、加密指令等场景。注意 ARM64 中前八个浮点型参数通过寄存器V0至V7传递, 如果函数有更多的参数, 那么超出的参数将通过堆栈传递。可通过不同后缀访问部分位宽:
    • Bn: 8 位(最低字节)
    • Hn: 16 位(低半字)
    • Sn: 32 位(低单字)
    • Dn: 64 位(低双字)
    • Qn: 128 位(完整寄存器)
  • SP(Stack pointer): 指向当前栈顶地址, 必须保持 ​​16 字节对齐​​(否则可能触发异常), 满递减栈
  • PC(Program Counter): 存储下一条指令地址。​​不能直接修改​​(通过 B、BL 等跳转指令隐式更新)
  • PSTATE: ARMv8/AArch64 架构中​​处理器状态的逻辑集合​​, 并非物理上的单一寄存器, 而是通过多个专用寄存器(Special-Purpose Registers)分散存储状态信息
    • ​​NZCV: 条件标志位(Negative, Zero, Carry, Overflow)
      • N: 结果为负时置 1
      • Z: 结果为零时置 1
      • C: 运算产生进位/借位时置 1
      • V: 有符号溢出时置 1
    • ​​DAIF: 中断屏蔽位(Debug, SError, IRQ, FIQ)
    • ​​CurrentEL: 当前异常级别(Exception Level, EL0-EL3)
    • ​​SPSel: 栈指针选择位(0=使用 SP_EL0, 1=使用 SP_ELx)
    • ​​PAN: 特权访问禁止位(Privileged Access Never), 启用后内核访问用户内存会触发异常
    • ​​UAO: 用户访问覆盖位(User Access Override), 控制非特权指令的行为
  • CPSR: ARMv7/AArch32 架构中的​​单一物理寄存器​​, 集中存储所有处理器状态信息
    • 条件标志位: NZCV(位置: bits 31-28)
    • ​​控制位
      • T: 指令集状态(0=ARM, 1=Thumb)
      • I/F: 中断屏蔽(IRQ/FIQ)
      • ......
  • XZR/WZR: 零寄存器, 硬编码为 ​​0​​, 用于简化指令, 读操作恒返回 0, 写操作无效

FP、LR 再思考

进入一个函数时, 会先将 LR FP 入栈, 然后更新 FP 为当前函数的 SP 也就是上一函数 FP 的地址, 之后再开辟所需栈空间, 假设又调用一个函数, 也是同样的流程, 等到函数开始返回时, 根据当前 FP 中存入的地址找到上一函数 FP 的值, 从栈中恢复前一函数的 FP, 获取 LR 也就是函数返回地址, 跳转 LR, 函数返回。

调用约定

  • ARM: 参数1R3 寄存器中, 剩下的参数从右往左一次入栈, ​​调用者(Caller)实现栈平衡, 返回值存放在 R0 中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
; 该代码是 arm-linux-androideabi-gcc + IDA PRO 生成的反汇编代码
.text:00008438                 MOV             R3, #5
.text:0000843C                 STR             R3, [SP,#0x1C+e] ; e
.text:00008440                 MOV             R3, #6
.text:00008444                 STR             R3, [SP,#0x1C+f] ; f
.text:00008448                 MOV             R3, #7
.text:0000844C                 STR             R3, [SP,#0x1C+g] ; g
.text:00008450                 MOV             R0, #1  ; a
.text:00008454                 MOV             R1, #2  ; b
.text:00008458                 MOV             R2, #3  ; c
.text:0000845C                 MOV             R3, #4  ; d
.text:00008460                 BL              add
.text:00008464                 STR             R0, [R11,#sum]
; 调用后平衡 e/f/g 占用的 12 字节栈空间
 
.text:000083C4                 EXPORT add
.text:000083C4                 STR             R11, [SP,#-4+var_s0]!    ; 保存 R11 原值
.text:000083C8                 ADD             R11, SP, #0              ; 保存 SP 到 R11
.text:000083CC                 SUB             SP, SP, #0x1C            ; 开辟所需栈空间
.text:000083D0                 STR             R0, [R11,#a]
.text:000083D4                 STR             R1, [R11,#b]
.text:000083D8                 STR             R2, [R11,#c]
.text:000083DC                 STR             R3, [R11,#d]
.text:000083E0                 LDR             R2, [R11,#a]
.text:000083E4                 LDR             R3, [R11,#b]
.text:000083E8                 ADD             R2, R2, R3
.text:000083EC                 LDR             R3, [R11,#c]
.text:000083F0                 ADD             R2, R2, R3
.text:000083F4                 LDR             R3, [R11,#d]
.text:000083F8                 ADD             R2, R2, R3
.text:000083FC                 LDR             R3, [R11,#e]
.text:00008400                 ADD             R2, R2, R3
.text:00008404                 LDR             R3, [R11,#f]
.text:00008408                 ADD             R2, R2, R3
.text:0000840C                 LDR             R3, [R11,#g]
.text:00008410                 ADD             R3, R2, R3
.text:00008414                 STR             R3, [R11,#sum]
.text:00008418                 LDR             R3, [R11,#sum]
.text:0000841C                 MOV             R0, R3                   ; R0 返回值
.text:00008420                 SUB             SP, R11, #0              ; 将 SP 恢复到刚进入函数时的值
.text:00008424                 LDR             R11, [SP+var_s0],#4      ; 恢复 R11 原值
.text:00008428                 BX              LR                       ; 返回
  • ARM64: 参数1X7 寄存器中, 剩下的参数从右往左一次入栈, 被调用函数(Callee)实现栈平衡, 返回值存放在 X0 中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
; 该代码是 aarch64-linux-android-gcc + IDA PRO 生成的反汇编代码
.text:0000000000400684                 MOV             W0, #9
.text:0000000000400688                 STR             W0, [SP,#0x40+i] ; i
.text:000000000040068C                 MOV             W0, #10
.text:0000000000400690                 STR             W0, [SP,#0x40+j] ; j
.text:0000000000400694                 MOV             W0, #11
.text:0000000000400698                 STR             W0, [SP,#0x40+k] ; k
.text:000000000040069C                 MOV             W0, #12
.text:00000000004006A0                 STR             W0, [SP,#0x40+l] ; l
.text:00000000004006A4                 MOV             W0, #1  ; a
.text:00000000004006A8                 MOV             W1, #2  ; b
.text:00000000004006AC                 MOV             W2, #3  ; c
.text:00000000004006B0                 MOV             W3, #4  ; d
.text:00000000004006B4                 MOV             W4, #5  ; e
.text:00000000004006B8                 MOV             W5, #6  ; f
.text:00000000004006BC                 MOV             W6, #7  ; g
.text:00000000004006C0                 MOV             W7, #8  ; h
.text:00000000004006C4                 BL              add
.text:00000000004006C8                 STR             W0, [X29,#0x20+sum]
 
.text:00000000004005E8                 EXPORT add
.text:00000000004005E8
.text:00000000004005E8                 SUB             SP, SP, #0x30        ; 开辟函数所需栈空间
.text:00000000004005EC                 STR             W0, [SP,#0x30+a]
.text:00000000004005F0                 STR             W1, [SP,#0x30+b]
.text:00000000004005F4                 STR             W2, [SP,#0x30+c]
.text:00000000004005F8                 STR             W3, [SP,#0x30+d]
.text:00000000004005FC                 STR             W4, [SP,#0x30+e]
.text:0000000000400600                 STR             W5, [SP,#0x30+f]
.text:0000000000400604                 STR             W6, [SP,#0x30+g]
.text:0000000000400608                 STR             W7, [SP,#0x30+h]
.text:000000000040060C                 LDR             W1, [SP,#0x30+a]
.text:0000000000400610                 LDR             W0, [SP,#0x30+b]
.text:0000000000400614                 ADD             W1, W1, W0
.text:0000000000400618                 LDR             W0, [SP,#0x30+c]
.text:000000000040061C                 ADD             W1, W1, W0
.text:0000000000400620                 LDR             W0, [SP,#0x30+d]
.text:0000000000400624                 ADD             W1, W1, W0
.text:0000000000400628                 LDR             W0, [SP,#0x30+e]
.text:000000000040062C                 ADD             W1, W1, W0
.text:0000000000400630                 LDR             W0, [SP,#0x30+f]
.text:0000000000400634                 ADD             W1, W1, W0
.text:0000000000400638                 LDR             W0, [SP,#0x30+g]
.text:000000000040063C                 ADD             W1, W1, W0
.text:0000000000400640                 LDR             W0, [SP,#0x30+h]
.text:0000000000400644                 ADD             W1, W1, W0
.text:0000000000400648                 LDR             W0, [SP,#0x30+i]
.text:000000000040064C                 ADD             W1, W1, W0
.text:0000000000400650                 LDR             W0, [SP,#0x30+j]
.text:0000000000400654                 ADD             W1, W1, W0
.text:0000000000400658                 LDR             W0, [SP,#0x30+k]
.text:000000000040065C                 ADD             W1, W1, W0
.text:0000000000400660                 LDR             W0, [SP,#0x30+l]
.text:0000000000400664                 ADD             W0, W1, W0
.text:0000000000400668                 STR             W0, [SP,#0x30+sum]
.text:000000000040066C                 LDR             W0, [SP,#0x30+sum]   ; X0 返回值
.text:0000000000400670                 ADD             SP, SP, #0x30        ; 平衡栈
.text:0000000000400674                 RET

参考链接

639K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8X3p5#2y4U0f1@1z5e0V1$3z5e0W2Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3k6r3g2@1j5h3W2D9M7#2)9J5c8U0M7&6x3U0V1@1x3U0j5I4

a56K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2j5%4y4V1L8W2)9J5k6h3&6W2N6q4)9J5c8Y4N6W2K9i4S2A6L8W2)9#2k6U0b7J5x3e0x3#2x3o6R3%4i4K6u0r3j5i4u0@1K9h3y4D9k6g2)9J5c8X3c8W2N6r3q4A6L8s2y4Q4x3V1j5I4x3e0p5J5y4U0x3%4x3U0l9`.


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 3天前 被nothing233编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回