背景介绍
arm指令分析学习环境ndk build + IDA6.8 + android 6.0手机
有符号除法
模板 argc/2^n
c代码
int main(int argc,char **argv){
printf("hello world");
//有符号除以2的幂
printf("\n%d",argc/2);
printf("\n%d",argc/4);
printf("\n%d",argc/8);
return 0;
}
汇编代码
.text:00000434 CODE16
.text:00000434 PUSH {R4-R6,LR} ; DATA XREF: .text:000004D0o
.text:00000434 ; .got:off_2FB4o
.text:00000436 MOVS R4, R0 ;R4 = argc
.text:00000438 LDR R0, =(aHelloWorld - 0x442)
.text:0000043A LDR R5, =(aD - 0x44A)
.text:0000043C ASRS R6, R4, #0x1F
.text:0000043E ADD R0, PC ; "hello world"
.text:00000440 BL j_j_printf
.text:00000444 LSRS R1, R4, #0x1F
.text:00000446 ADD R5, PC ; "\n%d"
.text:00000448 ADDS R1, R1, R4
.text:0000044A MOVS R0, R5
.text:0000044C ASRS R1, R1, #1
.text:0000044E BL j_j_printf
.text:00000452 LSRS R1, R6, #0x1E
.text:00000454 ADDS R1, R1, R4
.text:00000456 MOVS R0, R5
.text:00000458 LSRS R6, R6, #0x1D
.text:0000045A ASRS R1, R1, #2
.text:0000045C BL j_j_printf
.text:00000460 ADDS R1, R6, R4
.text:00000462 MOVS R0, R5
.text:00000464 ASRS R1, R1, #3
.text:00000466 BL j_j_printf
.text:0000046A MOVS R0, #0
.text:0000046C POP {R4-R6,PC}
回顾一下涉及到的指令
LSR语法
LSR Logical shift right by immediate
<Rm>, LSR #<shift_imm>
if shift_imm == 0 then
shifter_operand = 0
shifter_carry_out = Rm[31]
else /* shift_imm > 0 */
shifter_operand = Rm Logical_Shift_Right shift_imm
shifter_carry_out = Rm[shift_imm - 1]
ASR语法
ASR Arithmetic shift right by immediate
if shift_imm == 0 then
if Rm[31] == 0 then
shifter_operand = 0
shifter_carry_out = Rm[31]
else /* Rm[31] == 1 */
shifter_operand = 0xFFFFFFFF
shifter_carry_out = Rm[31]
else /* shift_imm > 0 */
shifter_operand = Rm Arithmetic_Shift_Right <shift_imm>
shifter_carry_out = Rm[shift_imm - 1]
两个指令的区别:LSR指令不用理会符号位,而ASR需要操作符号位
举例
r0 = 0x3f000000 要变成--->0x7e000000
MOVS R2,R0,LSL#1 会影响哪些标志位?为什么会影响C标志位?
会影响N 标志位,C标志位,Z标志位
//对于包含移位操作的非加法/减法,C被设置为由移位器移出值的最后一位
r2 = 0x7e000000 其中
被移除来的是0,所以C被设置为0
结果0X7E000000 是正数,所以N标志位为1
结果不等于0,所以Z标志位为0
模板 argc/2^n + 1 c代码
int main(int argc,char **argv){
printf("\n%d",argc/3);
return 0;
}
汇编代码
.text:AB1C3464 PUSH {R3,LR}
.text:AB1C3466 MOVS R1, #3 ;除数 3
.text:AB1C3468 BL sub_AB1C3528
.text:AB1C346C MOVS R1, R0
.text:AB1C346E LDR R0, =(unk_AB1C4760 - 0xAB1C3474)
.text:AB1C3470 ADD R0, PC ; unk_AB1C4760 ; char *
.text:AB1C3472 BL j_j_printf
.text:AB1C3476 MOVS R0, #0
.text:AB1C3478 POP {R3,PC}
---------------------------------------------------------------
.text:000005D0 sub_5D0 ; CODE XREF: sub_464+1Ap
.text:000005D0 CMP R1, #0
.text:000005D2 BEQ sub_658
.text:000005D4 PUSH {R4}
.text:000005D6 MOVS R4, R0
.text:000005D8 EORS R4, R1
.text:000005DA MOV R12, R4
.text:000005DC MOVS R3, #1
.text:000005DE MOVS R2, #0
.text:000005E0 CMP R1, #0
.text:000005E2 BPL loc_5E6
.text:000005E4 NEGS R1, R1
.text:000005E6
.text:000005E6 loc_5E6 ; CODE XREF: sub_5D0+12j
.text:000005E6 CMP R0, #0
.text:000005E8 BPL loc_5EC
.text:000005EA NEGS R0, R0
.text:000005EC
.text:000005EC loc_5EC ; CODE XREF: sub_5D0+18j
.text:000005EC CMP R0, R1
.text:000005EE BCC loc_64A
.text:000005F0 MOVS R4, #0x10000000
.text:000005F4
.text:000005F4 loc_5F4 ; CODE XREF: sub_5D0+30j
.text:000005F4 CMP R1, R4
.text:000005F6 BCS loc_602
.text:000005F8 CMP R1, R0
.text:000005FA BCS loc_602
.text:000005FC LSLS R1, R1, #4
.text:000005FE LSLS R3, R3, #4
.text:00000600 B loc_5F4
.text:00000602 ; ---------------------------------------------------------------------------
.text:00000602
.text:00000602 loc_602 ; CODE XREF: sub_5D0+26j
.text:00000602 ; sub_5D0+2Aj
.text:00000602 LSLS R4, R4, #3
.text:00000604
.text:00000604 loc_604 ; CODE XREF: sub_5D0+40j
.text:00000604 CMP R1, R4
.text:00000606 BCS loc_612
.text:00000608 CMP R1, R0
.text:0000060A BCS loc_612
.text:0000060C LSLS R1, R1, #1
.text:0000060E LSLS R3, R3, #1
.text:00000610 B loc_604
.text:00000612 ; ---------------------------------------------------------------------------
.text:00000612
.text:00000612 loc_612 ; CODE XREF: sub_5D0+36j
.text:00000612 ; sub_5D0+3Aj ...
.text:00000612 CMP R0, R1
.text:00000614 BCC loc_61A
.text:00000616 SUBS R0, R0, R1
.text:00000618 ORRS R2, R3
.text:0000061A
.text:0000061A loc_61A ; CODE XREF: sub_5D0+44j
.text:0000061A LSRS R4, R1, #1
.text:0000061C CMP R0, R4
.text:0000061E BCC loc_626
.text:00000620 SUBS R0, R0, R4
.text:00000622 LSRS R4, R3, #1
.text:00000624 ORRS R2, R4
.text:00000626
.text:00000626 loc_626 ; CODE XREF: sub_5D0+4Ej
.text:00000626 LSRS R4, R1, #2
.text:00000628 CMP R0, R4
.text:0000062A BCC loc_632
.text:0000062C SUBS R0, R0, R4
.text:0000062E LSRS R4, R3, #2
.text:00000630 ORRS R2, R4
.text:00000632
.text:00000632 loc_632 ; CODE XREF: sub_5D0+5Aj
.text:00000632 LSRS R4, R1, #3
.text:00000634 CMP R0, R4
.text:00000636 BCC loc_63E
.text:00000638 SUBS R0, R0, R4
.text:0000063A LSRS R4, R3, #3
.text:0000063C ORRS R2, R4
.text:0000063E
.text:0000063E loc_63E ; CODE XREF: sub_5D0+66j
.text:0000063E CMP R0, #0
.text:00000640 BEQ loc_64A
.text:00000642 LSRS R3, R3, #4
.text:00000644 BEQ loc_64A
.text:00000646 LSRS R1, R1, #4
.text:00000648 B loc_612
.text:0000064A ; ---------------------------------------------------------------------------
.text:0000064A
.text:0000064A loc_64A ; CODE XREF: sub_5D0+1Ej
.text:0000064A ; sub_5D0+70j ...
.text:0000064A MOVS R0, R2
.text:0000064C MOV R4, R12
.text:0000064E CMP R4, #0
.text:00000650 BPL loc_654
.text:00000652 NEGS R0, R0
.text:00000654
.text:00000654 loc_654 ; CODE XREF: sub_5D0+80j
.text:00000654 POP {R4}
.text:00000656 BX LR
.text:00000656 ; End of function sub_5D0
main函数的 BL处的 sub_AB1C3528(sub_5D0) ARM和Windows的处理方式很不一样,这里直接一个函数代替了.
它实现了argc/3的计算
回顾涉及到的指令
B 跳转 + 条件执行 可以组合的指令举例: BPL PMI BCC BCS BEQ BNE
BPL B(B plus)
含义:if n == 0 then B(jmp)
NEGS R1,R1
含义:R1 = 0 - R1 if R1 > 0 set carry = 0,set z = 0,set n = 1
set R1 = -1
NEGS R1,R1 r1 = 0 - 0xffffffff = 0x100000000(借位) - 0xffffffff = 1, set carry = 0,set z = 0,set n = 0
set R1 = 0
NEGS R1,R1, r = 0 - 0 = 0 set carry = 1,set z = 1,set n = 0
set R1 = 1
NEGS R1,R1, r = 0 - 1 = 0x100000000 - 1 = 0xffffffff = -1,set carry 0 ,set z = 0,set n = 1
CMP R0,R1
含义:RO - R1 if R0 > R1 set carry = 1,set z = 0,set n = 0 ,set v = 0
BCC loc_ab1xxx if carry = 0 jmp loc_ab1xxx
翻译成C代码if(R0 >= R1){
...
}
CMP R1, R4
含义 R1 - R4 if R1 > R4 set carry = 1 set z = 0 set n = 0, set v = 0
BCS loc_AB1C355A if carry = 1 jmp loc_AB1C355A
翻译成C代码
if(R1 < R4){
...
}
无符号除法
(unsigned int )argc/2 ^n
c代码
int main(int argc,char **argv){
printf("\n%d",(unsigned int)argc/2);
printf("\n%d",(unsigned int)argc/8);
printf("\n%d",(unsigned int)argc/4);
return 0;
}
汇编代码
.text:00000434 PUSH {R3-R5,LR}
.text:00000436 MOVS R4, R0
.text:00000438 LDR R5, =(unk_15D8 - 0x440)
.text:0000043A LSRS R1, R0, #1 argc/2
.text:0000043C ADD R5, PC ; unk_15D8
.text:0000043E MOVS R0, R5 ; char *
.text:00000440 BL j_j_printf
.text:00000444 LSRS R1, R4, #4 argc/16
.text:00000446 MOVS R0, R5 ; char *
.text:00000448 BL j_j_printf
.text:0000044C MOVS R0, R5 ; char *
.text:0000044E LSRS R1, R4, #3 argc/8
.text:00000450 BL j_j_printf
.text:00000454 MOVS R0, #0
.text:00000456 POP {R3-R5,PC}
基本没有什么新的指令 就一个操作LSRS ,直接右移操作
(unsigned int )argc/2 ^n + 1
int main(int argc,char **argv){
printf("\n%d",(unsigned int)argc/3);
printf("\n%d",(unsigned int)argc/5);
printf("\n%d",(unsigned int)argc/7);
printf("\n%d",(unsigned int)argc/9);
return 0;
}
汇编代码
.text:00000464 sub_464 ; DATA XREF: start+4Co
.text:00000464 ; .got:off_2FB0o
.text:00000464 PUSH {R3-R5,LR}
.text:00000466 MOVS R1, #3
.text:00000468 MOVS R5, R0
.text:0000046A BL sub_55C
.text:0000046E LDR R4, =(unk_16DC - 0x476)
.text:00000470 MOVS R1, R0
.text:00000472 ADD R4, PC ; unk_16DC
.text:00000474 MOVS R0, R4 ; char *
.text:00000476 BL j_j_printf
.text:0000047A MOVS R0, R5
.text:0000047C MOVS R1, #5
.text:0000047E BL sub_55C
.text:00000482 MOVS R1, R0
.text:00000484 MOVS R0, R4 ; char *
.text:00000486 BL j_j_printf
.text:0000048A MOVS R0, R5
.text:0000048C MOVS R1, #7
.text:0000048E BL sub_55C
.text:00000492 MOVS R1, R0
.text:00000494 MOVS R0, R4 ; char *
.text:00000496 BL j_j_printf
.text:0000049A MOVS R0, R5
.text:0000049C MOVS R1, #9
.text:0000049E BL sub_55C
.text:000004A2 MOVS R1, R0
.text:000004A4 MOVS R0, R4 ; char *
.text:000004A6 BL j_j_printf
.text:000004AA MOVS R0, #0
.text:000004AC POP {R3-R5,PC}
这里仍然是调用一个函数实现(unsigned int )arg/2^n +1
---------------------------------------------------------------------------------
.text:0000055C sub_55C ; CODE XREF: sub_464+6p
.text:0000055C ; sub_464+1Ap ...
.text:0000055C CMP R1, #0
.text:0000055E BEQ loc_5CA
.text:00000560 MOVS R3, #1
.text:00000562 MOVS R2, #0
.text:00000564 PUSH {R4}
.text:00000566 CMP R0, R1
.text:00000568 BCC loc_5C4
.text:0000056A MOVS R4, #0x10000000
.text:0000056E
.text:0000056E loc_56E ; CODE XREF: sub_55C+1Ej
.text:0000056E CMP R1, R4
.text:00000570 BCS loc_57C
.text:00000572 CMP R1, R0
.text:00000574 BCS loc_57C
.text:00000576 LSLS R1, R1, #4
.text:00000578 LSLS R3, R3, #4
.text:0000057A B loc_56E
.text:0000057C ; ---------------------------------------------------------------------------
.text:0000057C
.text:0000057C loc_57C ; CODE XREF: sub_55C+14j
.text:0000057C ; sub_55C+18j
.text:0000057C LSLS R4, R4, #3
.text:0000057E
.text:0000057E loc_57E ; CODE XREF: sub_55C+2Ej
.text:0000057E CMP R1, R4
.text:00000580 BCS loc_58C
.text:00000582 CMP R1, R0
.text:00000584 BCS loc_58C
.text:00000586 LSLS R1, R1, #1
.text:00000588 LSLS R3, R3, #1
.text:0000058A B loc_57E
.text:0000058C ; ---------------------------------------------------------------------------
.text:0000058C
.text:0000058C loc_58C ; CODE XREF: sub_55C+24j
.text:0000058C ; sub_55C+28j ...
.text:0000058C CMP R0, R1
.text:0000058E BCC loc_594
.text:00000590 SUBS R0, R0, R1
.text:00000592 ORRS R2, R3
.text:00000594
.text:00000594 loc_594 ; CODE XREF: sub_55C+32j
.text:00000594 LSRS R4, R1, #1
.text:00000596 CMP R0, R4
.text:00000598 BCC loc_5A0
.text:0000059A SUBS R0, R0, R4
.text:0000059C LSRS R4, R3, #1
.text:0000059E ORRS R2, R4
.text:000005A0
.text:000005A0 loc_5A0 ; CODE XREF: sub_55C+3Cj
.text:000005A0 LSRS R4, R1, #2
.text:000005A2 CMP R0, R4
.text:000005A4 BCC loc_5AC
.text:000005A6 SUBS R0, R0, R4
.text:000005A8 LSRS R4, R3, #2
.text:000005AA ORRS R2, R4
.text:000005AC
.text:000005AC loc_5AC ; CODE XREF: sub_55C+48j
.text:000005AC LSRS R4, R1, #3
.text:000005AE CMP R0, R4
.text:000005B0 BCC loc_5B8
.text:000005B2 SUBS R0, R0, R4
.text:000005B4 LSRS R4, R3, #3
.text:000005B6 ORRS R2, R4
.text:000005B8
.text:000005B8 loc_5B8 ; CODE XREF: sub_55C+54j
.text:000005B8 CMP R0, #0
.text:000005BA BEQ loc_5C4
.text:000005BC LSRS R3, R3, #4
.text:000005BE BEQ loc_5C4
.text:000005C0 LSRS R1, R1, #4
.text:000005C2 B loc_58C
.text:000005C4 ; ---------------------------------------------------------------------------
.text:000005C4
.text:000005C4 loc_5C4 ; CODE XREF: sub_55C+Cj
.text:000005C4 ; sub_55C+5Ej ...
.text:000005C4 MOVS R0, R2
.text:000005C6 POP {R4}
.text:000005C8 BX LR
.text:000005CA ; ---------------------------------------------------------------------------
.text:000005CA
.text:000005CA loc_5CA ; CODE XREF: sub_55C+2j
.text:000005CA NOP
.text:000005CC BX PC
.text:000005CC ; ---------------------------------------------------------------------------
.text:000005CE ALIGN 4
.text:000005D0 CODE32
.text:000005D0
.text:000005D0 loc_5D0 ; CODE XREF: sub_55C+70j
.text:000005D0 CMP R0, #0
.text:000005D4 MOVNE R0, #0xFFFFFFFF
.text:000005D8 B loc_5F0
.text:000005D8 ; ---------------------------------------------------------------------------
.text:000005DC DCD 0xD0F42900, 0xF7FFB503, 0xBC0EFFBD, 0x1A894342, 0x46C04718
.text:000005F0 ; ---------------------------------------------------------------------------
.text:000005F0
.text:000005F0 loc_5F0 ; CODE XREF: sub_55C+7Cj
.text:000005F0 STMFD SP!, {R1,LR}
.text:000005F4 MOV R0, #8 ; int
.text:000005F8 BL raise
.text:000005FC LDMFD SP!, {R1,PC}
.text:000005FC ; End of function sub_55C
.text:000005FC
.text:00000600 CODE16
ARM除法指令小结
除以2的幂,编译器直接采用移位操作实现,由符号使用3条指令 ASRS \ADDS\ LSRS操作,无符号直接使用LSLS指令操作
除以非2的幂 编译器处理的很干脆,无符号和有符号编译时没有采用什么花哨的优化,直接调用一个函数来实现除法