Arm入门第七讲,Thumb 与ARM子程序。

Arm入门第七讲,Thumb 与ARM子程序。

一丶Thumb

1.1 什么是Thumb

Thumb 指令集是16bit指令集,是为了兼容数据总线宽度为16位的应用系统,Arm体系结构除了支持执行效率很高的32位Arm指令集以外,同时也支持16位的Thumb指令集。可以说Thumb是Arm指令集的一个子集,允许指令编码为16位的长度。 与等价的32位代码相比较,Thumb指令集在保留32代码的优势的同时,又大大节省了空间。

1.2 Thumb指令集的由来

Thumb指令集是从ARMV4T之后的ARM处理器有的指令集。是一种16bit指令模式,叫做Thumb. 他可以看做是ARM指令压缩形式的子集,它是为减少代码量而提出,具有16bit的代码密度。

Thumb指令T恤并不完整,只支持通用功能,必要时仍然需要ARM指令。 比如进入异常。

1.3 Thumb的特点

1.Thumb代码所需要的存储空间为Arm代码的 60%-70% 毕竟指令短,那么自然就会占用空间。

2.Thumb代码使用的指令数比ARM代码多30%--40%

3.若使用32位的存储器,那么ARM代码比Thumb代码块40%

4.若使用16位存储器,Thumb则比ARM代码快40%-50%

5.与ARM代码比较,使用Thumb代码,存储器的功耗会降低30%

显然是各有优缺点的。

1.4 Thumb与Arm的却别

区别如下:

1. 分支指令: 跳转的范围小,除了B指令外,其他都是无条件跳转。
2. 数据处理指令: Thumb指令只有两个操作数,而ARM指令则是3个操作数。
3. 单寄存器加载/存储指令: Thumb指令只能访问R0-R7寄存器。
4. 多寄存器加载/存储指令: Thumb指令只能访问R0-R7的子集
5. Thumb特有指令: push 和POP是它特有的指令,作用于R13(sp)寄存器。

编写Thumb 指令的时候,要先使用伪指令CODE16声明,而且在ARM指令中要使用BX 指令来跳转到Thumb指令,BX的指令地址低位为1则是表示THUMB指令,否则就是ARM指令。

编写ARM指令的时候可以用 CODE32声明,然后如果遵循一定的调用规则,则Thumb子程序和ARM子程序可以互相调用。

二丶ARM的ATPCS调用标准

ATPCS标准 可以理解为ARM是怎么使用堆栈的。

那么在此之前需要熟悉 调用约定的知识。 X86的栈操作知识等等。

2.1 调用约定

调用约定分为如下:

  • cdecl调用约定

    该调用约定遵循以下规则:

    参数入栈顺序是从右向左

    栈平衡负责 是由调用者来平。

    如函数A 调用函数B 在这里A就是调用者 B就是被调用者。

  • stdcall 调用约定

    入栈规则: 参数从右向左入栈

    栈平衡负责: 被调用者负责

    如B函数接受2个参数。 A调用B 在B执行完毕之后会操作栈来保证栈平衡。

  • fastcall调用约定

    参数入栈顺序: 函数的第一第二个参数通过ecx和edx入栈。 x64的结构下还有r8 r9(寄存器), 剩余的参数则从右向左入栈。

    栈平衡:被调用者进行栈平衡。 (如果是x64那么则是调用者负责)

返回值的存放:

​ 返回值放在EAX和RAX(x64)中

下面是调用堆栈图:

2.2 ARM调用约定

ARM函数之间互相调用遵循的规则就是ATPCS(ARM-THUMB Procedure Call Standard) ATPCS主要是定义了函数调用时参数的传递规则以及函数的返回规则。 它很类似于X64架构下的fastcall调用。

它们有一个共同的特点就是寄存器多,有大量寄存器可用。

  • 传参方式

    R0 -R3是传递函数的第1到第四个参数的,超出的部分从右向左通过栈传递。

    在X64下再是 RCX RDX R8 R9寄存器进行参数传递。所以这里很雷同。

  • 栈平衡

    ​ 栈平衡则是由调用者进行栈平衡的。

  • 结果保存

    1.结果为32位整数的时候,可以通过寄存器R0来返回。

    2.结果是64位整数的时候,可以通过R0 R1返回。

    3.结果是浮点数,那么通过浮点寄存器F0 D0 或者S0返回。

    4.结果是符合浮点数,那么可以通过寄存器F0 -FN 或者D0 -DN来进行返回。

  • 局部变量

    R4-R11是用来保存局部变量的,如果用到了那么函数在进入的时候就要先保存,这点类似于x86环境下的pushad pushfd等指令,保存寄存器环境。 而在返回的时候,这些寄存器的值也要进行恢复。

    Thumb指令只能使用R4-R7,R11也可以做FP寄存器。也就是x86的EBP

  • 返回地址

    返回地址使用R14寄存器进行保存(也叫做LR寄存器)

    x86的返回地址在栈中保存。

  • 栈顶寄存器

    ​ R13是作为栈顶寄存器的,也就是SP寄存器。 x86下则是使用ESP

  • 栈基址寄存器

    ​ R11作为栈基址寄存器的 也就是FP指令。 x86下则是EBP

  • 下一条指令寄存器

    R15寄存器,也叫做PC寄存器。 是指向下一条要执行指令的,类似于X86下的EIP寄存器。

  • 备份寄存器

    ​ R12寄存器主要作用于子程序内部的,也叫做IP寄存器。 内部过程调用寄存器,可以备份保存 SP(R13) LR(R14)寄存器等。

堆栈使用的FD满递减栈,也就是跟X86是一样的。

posted @ 2021-07-17 19:00  Android_IBinary  阅读(1444)  评论(0编辑  收藏  举报