PowerPC指令
内容参考
《PPC Vers202 Book1 public.pdf》
基础内容
基础数据结构
| 基础结构 | 汉语名 | 长度 |
|---|---|---|
| Quadword | 四字 | 128bits |
| Doubleword | 双字 | 64bits |
| Word | 字 | 32bits |
| Halfword | 半字 | 16bits |
| Byte | 字节 | 8bits |
数字表示
二进制 :0bnnnn
十六进制:0xnnnn
通用寄存器
PPC中通用寄存器供32个,编号为 r0-r31,分别如下:
| 寄存器名 | 描述 |
|---|---|
| r0 | 函数开始时使用? |
| r1 | 堆栈指针,IDA中标识为 $sp |
| r2 | 内容表指针,IDA中标识为 rtoc |
| r3 | 函数调用中作为第一参数,以及返回值 |
| r4-r10 | 函数或系统调用开始的参数 |
| r11 | 用在指针的调用和当做一些语言的环境指针 |
| r12 | 用于异常处理和glink代码 |
| r13 | 保留作为系统线程ID |
| r14-r31 | 作为本地变量,非易失性 |
专用寄存器
| 寄存器名 | 描述 |
|---|---|
| lr | 链接寄存器,它用来存放函数调用结束处的返回地址。 |
| ctr | 计数寄存器,循环计数器,随特定转移操作而递减。 |
| xer | 定点异常寄存器,存放整数运算操作的进位以及溢出信息。 |
| msr | 机器状态寄存器,用来配置微处理器的设定。 |
| cr | 条件寄存器,它分成8个4位字段,cr0-cr7,它反映了某个算法操作的结果并且提供条件分支的机制。 |
浮点寄存器
由于样本逆向过程中未涉及浮点寄存器,所以这里不总结了。
指令格式
四字节定长指令系统,字(4字节)对齐,因此,当在指令中要表达指令地址时,低两位二进制位是无效的,对于任意合法的指令地址,低二位二进制都必然是0。
PPC全部指令集,被分为15种不同的指令格式,每种指令格式的解码方法各不相同。
常见指令列表:
基础运算
| 指令 | 指令格式 | 指令功能 |
|---|---|---|
| divw | divw rd,rs1,rs2 | rd=rs1/rs2 |
| add | add r11, r11, r9 | r11 = r11+r9 |
| addi | addi rd,rs,xxx | rd = rs + xxx 立即数加 |
| mullw | mullw r0, r0, r3 | r0 = r0*r3 |
| srawi | srawi r0, r11, 8 | r0 = r11 » 8 |
| slwi | slwi r0, r0, 8 | r0 = r0 « 8 |
| subf | subf r0, r0, r8 | r0 = r8-r0 |
| addze | addze r0, r0 | 推测是数值扩充指令。 0xf -> 0x0f 这种含义 | |
| clrlwi | clrlwi rd,rs,imm | rd=rs & ((1«(32-imm)) -1) 将 rs 的高imm 位清零,结果放置于 rd寄存器 |
寄存器操作指令
| 指令 | 指令格式 | 指令功能 |
|---|---|---|
| mflr | mflr r0 | r0=lr 函数调用起始使用,一般用于保存函数返回地址 |
| mtlr | mtlr r0 | lr=r0 函数结尾使用,还原函数返回地址,常和blr指令配合使用 |
| stwu | stwu rs,imm(rd) | 保存rs寄存器内容到内存 |
| stbx | stbx rs,rd1,rd2 | mem[rd1+rd2] = rs 内存赋值 |
| li | li rd,imm | rd = imm 寄存器赋值 |
| lbzx | lbzx rd,rs1,rs2 | rd = [rs1+rs2] 内存取值 |
| lis | lis rd,imm | 寄存器高位赋值 r9=xxx « 16 常和 addi 配合使用 |
| lbz | lbz rd,imm(rs) | rd=mem[rs+imm] 按字节取 |
| lhz | lhz rd, imm(rs) | rd=mem[rs+imm] 按半字取值 |
| lwz | lwz rd, imm(rs) | rd=mem[rs+imm] 按字取值 |
程序流控制相关指令
| 指令 | 指令格式 | 指令功能 |
|---|---|---|
| mtctr | mtctr rs | 用rs寄存器的值更新计数器ctr,一般用于循环判断 |
| bdnz | bdnz imm | if (ctr!=0) goto pc+imm 检查ctr寄存器,并按偏移跳转 |
| cmpwi | cmpwi rd, rs, imm | rd=rs-imm 比较指令,结果放rd寄存器,常和跳转指令连用 |
| ble | ble rs, imm | if (rs <=0 ) goto pc+imm 按偏移跳转 |
| cmpw | cmpw rd, rs1, rs2 | rd=rs1-rs2 比较指令,结果放rd寄存器,常和跳转指令连用 |
| bgt | bgt rs,imm | if(rs>0) goto pc+imm 按偏移跳转 |
| bl | bl imm | 以imm 地址为目标地址,跳转。 |
| blr | blr | 以lr寄存器的值为目标地址。常用在函数退出位置 |
总结
PowerPC(PPC)指令体系,为RISC指令集,同时也是32位定长指令,从已掌握的指令结构体系来看,除 Motorola 那个嵌入式指令集为变长指令集外,其他嵌入式CPU均为定长指令体系,定长指令的优点在于取指方便,更方便CPU从硬件层面实现流水线指令处理,从逆向结果来看,PowerPC同样具有延时指令的特点(流水线型嵌入式指令体系均有这一特点)。
PowerPC对基础数据结构的定义同其他体系不同。这是一个在算法逆向中需要注意的点。
由于指令体系为32位定长指令,而寄存器也为32位,所以在寄存器赋值时,无法在一条指令中完成32位立即数的操作,这也是所有嵌入式CPU的共性问题。