入门 ARM 汇编(二)—— 寻址方式
忧愁他整天拉着我的心,像一个琴师操练他的琴;悲哀像是海礁间的飞涛:看他那汹涌,听他那呼号!—— 徐志摩·四行诗一首
ilocker:关注 Android 安全(新手) QQ: 2597294287
立即数寻址
源操作数为立即数,多用于给寄存器赋初值。
指令执行后,R1 寄存器的值就是 2。
立即数也可为:十六进制,# 后跟 0x;八进制,# 后跟 0;二进制,# 后跟 0b。
立即数有合法性限制,具体可 google 相关资料。
寄存器寻址
操作数的值在寄存器中。
指令执行后,R0 = R5。
速度仅次于立即数寻址。
寄存器移位寻址
类似于寄存器寻址,只是在操作前先对源寄存器操作数进行移位操作。
- LSL:逻辑左移,低位补 0
- LSR:逻辑右移,高位补 0
- ASR:算术右移,移位过程中保持符号位不变(如果源操作数为正数,高位补 0,否则补 1)
- ROR:循环右移,移出的低位填入空出的高位
- RRX:带扩展的循环右移,高位用进位标志位 C 填充(标志位 C 在 CPSR 中)
指令执行后,R1 = R8 * 8。
.W 表示生成 32 位指令。
寄存器间接寻址
由寄存器值指出操作数在内存中的地址。
将 R4 寄存器值作为地址,取出此地址中的值赋给 R6。
基址寻址
与寄存器间接寻址有些类似,多用于查表、数组访问等操作。
将 R6 寄存器值加 1 作为地址,取出此地址中的值赋给 R0。
LDR 后面加 B,表示是从内存加载字节数据到寄存器。
多寄存器寻址
LDM 是数据加载指令,后缀 IA 表示每执行完一次加载操作后 R6 寄存器的值自增 1 个字。
指令执行后,R0 = [R6],R1 = [R6 + #4],R2 = [R6 + #8],R3 = [R6 + #12]。
ARM 指令集中,一个“字”表示一个 32 位的数值。
多寄存器寻址的一条指令最多可以完成 16 个通用寄存器值的传送。
R6 后面的叹号,表示指令执行后,更新基址寄存器 R6 的值。否则,指令执行后 R6 的值是不变的。
堆栈寻址
LDM 和 STM 作为指令前缀,表示多寄存器寻址。
FA、EA、FD、ED 作为指令后缀(指明堆栈生长方向和堆栈指针指向位置等,后面会继续学习)。
将数据出栈,保存到 R0、LR,多用于恢复子程序现场。
块拷贝寻址
LDM 和 STM 作为指令前缀,表示多寄存器寻址。
IA、DA、IB、DB 作为指令后缀(指明基址寄存器的递增或递减方式,后面会继续学习)。
示例同“多寄存器寻址”。
相对寻址
将程序计数器 PC 的当前值作为基地址,加上偏移量后得到操作数的有效地址。
这里的 BL 采用的就是相对寻址,标号 __libc_format_log 就是偏移量。
学习资料: 《Android 软件安全与逆向分析》