ARM指令集
ARM指令集基础知识
前段时间学习了下ARM指令集的基础只是,方便往后记录学习
ARM简介
在CTF比赛中,大部分的题目都是由x86,x86_64的程序。这一类的程序属于intel处理器所支持的,但是在我们现实中比如安卓,网络设备,智能家电等等使用ARM架构的处理器要比intel多很多。
Intel和arm的主要区别的是指令集:
*cisc复杂指令集
*risc精简指令集
精简指令集会通过减少每条指令时钟周期来缩短执行时间,以达到更快的执行命令,但是因为命令比较少,所以实现功能的时候,会比intel长
其次,在x86架构中大多数指令都是可以直接对内存数据进行操作,在ARM上,必须将内存中的数据移动到寄存器上面才可以进行操作。
Intel和arm更多的差别是:
- 在arm中,多数指令用于条件执行
- 在intel x86和x86_64一系列处理器用little-endian格式
- 在v3处理器之前arm的体系结构还是little-endian字节序,从此之后arm体系结构便改为了BI-endian字节序,并允许可切换字节序。
ARM数据类型和寄存器
字节序:
有两个查看字节的基本方法:小端和大端,在ARM体系中具有允许可切换字节序的设置。
寄存器:
- 寄存器的数量取决于arm的版本
32位
- 在ARM32位中有30个寄存器,前16个寄存器可以在用户模式下进行访问,其他寄存器则需要在特权软件执行中使用,也就是R0-R15寄存器可以在任何权限模式下使用,这16个寄存器可以分为俩组:通用寄存器(r0-r11)和专用寄存器(r12-r15)
- R0-R12:可以在常规操作时间内用于存储临时值
- R0:在算术操作时间内被叫做累加器,用于存储之前调用的函数结果,个人感觉象rax
- R7:用于存储系统的调用号(重点)
- R11:用来帮助我们跟踪用作帧指针的堆栈边界
- 在ARM的系统调用前四个参数存储在R0-R3!!!!!!(重点)
- R13:sp(堆栈指针)指向堆栈顶部
- R14:LR(链接寄存器),当我们进行功能调用的时候,链接寄存器会将使用的一个内存地址进行更新,该内存地址引用了从其开始该功能的下一条指令。这样做可以使得程序回到“父”函数,改函数在子函数完成后启动子函数系统调用
- R15:PC(程序计数器)PC自动增加执行指令的大小,在ARM状态下,此大小始终会是4个字节,在thumb模式下,此大小始终为2个字节,当实行转移指令时,PC会保留目标地址,在执行期间,PC在ARM状态下+8(在thumb模式下+4),这和X86的状态下不同,X86的PC始终指向下一条命令
当参数少于4个的时候,子程序间会通过寄存器R0-R3来传递参数,当多于4个的时候,会通过栈来传递参数。
在子程序中,使用R4-R11会保存局部变量,若是我们使用需要入栈保存,子程序返回前需要恢复这些寄存器,R12是临时寄存器不需要恢复。
子程序返回32位的整数时,使用r0返回,当返回64的整数的时候,会使用r0来返回低位,r1返回高位。
64位
- X0~x7:用于传递子程序的参数和结果,使用时不需要保存,多余的参数利用堆栈传递,64位返回结果采用x0表示,128位返回结果采用x1:x0
- X8:用于保存子程序返回地址,尽量不要用
- X9~X15:临时寄存器,用的时候不要保存
- X16~x17:子程序内部调用的寄存器,使用的时候不需要保存,尽量不要用
- X18:平台寄存器,他的使用跟平台相关,尽量不要用
- X19~X28:临时寄存器,使用的时候必须保存。
- X29:帧指针寄存器,用于连接栈帧,使用时需要保存
- X30:LR(链接寄存器)
- X31:SP(堆栈指针寄存器)或ZXR(零寄存器)
子程序调用必须要保存的寄存器X19~X29和sp(X31),不要保存的寄存器就是X0~X7和X9~X15
32位和64位寄存器的差异
- 栈arm32位下,前4个参数都是通过r0-r3传递,第四个参数就需要通过sp来访问第五个参数就需要通过sp+4访问,第n个参数需要通过sp+4*(n-4)来访问。
- Arm64位下,前8个餐宿是通过x0~x7传递,第8个参数需要通过sp访问,第9个参数需要通过sp+8访问,第n个参数需要通过sp+8*(n-8)来访问.
- ARM指令在32和64位下并非不是完全一样的,但是大部分的指令都是通用的,特别的就是“ MOV r2,r1,lsl #2”,只有在ARM32位下支持,他就等于ARM64位下的“ lsl r2,r1,#2”一样
- 还有一些ARM32位存在的指令在ARM64位下是不存在的比如:vswl指令,条件执行指令subgt,addle等。。。
ARM指令集
Arm处理器中有两个可以运行的主要状态,此处不包括lazelle:ARM和thumb,这俩个状态的主要区别时指令集,其中arm的指令始终是32位,tmumb下的指令始终是16位(也可以是32位),现在,ARM加入了增强的tmumb指令集(tmumbv2)
Thumb和ARM一样也有不同的版本
- Thumb-1 (16位指令): 在ARMv6和更早的体系结构中使用
- Thumb-2(16位和32位指令): 通过添加更多指令并使它们的宽度为16位或32位(ARMv6T2,ARMv7) 来扩展Thumb-1
- ThumbEE:包括一些针对动态生成的代码的更改和添加
ARM和Thumb之间的区别
- 条件执行: ARM状态下的所有指令均支持条件执行。某些ARM处理器版本允许使用“it”指令在Thumb中有条件执行。
- 32位ARM和Thumb指令:32位Thumb指令带有.w后缀。
- 桶式移位器 (barrel shifter) 是ARM模式的另一个独特功能。它可以用于将多个指令缩小为一个。比如,你可以使用左移,而不是使用两条指令将寄存器乘以2并使用mov将结果存储到另一个寄存器中: mov r1, r0, lsl #1 ; r1 = r0 * 2
ARM指令简介
汇编语言由指令构成,而指令是主要的构建块。ARM指令通常后跟或两个操作数,并且通常使用以下模板
MNEMONIC {S) {condition){Rd],Operand1,Operand2
注意,由于ARM指令集的灵活性,并非所有指令都使用模板中提供的所有字段。其中,条件字段与CPSR寄存器的值紧密相关,或者确切地说,与寄存器内特定位的值紧密相关
Operand2被称为灵活操作数,因为我们可以以多种形式使用它,例如我们可以将这些表达式用作Operand2:
下面以一些常见指令为例::