循环&选择
cmp(Compare)比较指令
CMP 把一个寄存器的内容和另一个寄存器的内容或立即数进行比较。但不存储结果,只是正确的更改标志。
一般CMP做完判断后会进行跳转,后面通常会跟上B指令
BL 标号:跳转到标号处执行
B.LT 标号:比价结果是小于(less than),执行标号,否则不跳转
B.LE 标号:比较结果是小于等于(less than or qeual to),执行标号,否则不跳转
B.GT 标号:比较结果是大于(greater than),执行标号,否则不跳转
B.GE 标号:比较结果是大于等于(greater than or equal to),执行标号,否则不跳转
B.EQ 标号:比较结果是等于(equal to),执行标号,否则不跳转
B.NE 标号:比较结果是不等于(not equal to),执行标号,否则不跳转
B.LS 标号:比较结果是无符号小于等于,执行标号,否则不跳转
B.LO 标号:比较结果是无符号小于,执行标号,否则不跳转
B.HI 标号:比较结果是无符号大于,执行标号,否则不跳转
B.HS 标号:比较结果是无符号大于等于,执行标号,否则不跳转
一.分析if 和全局变量的汇编代码
0x10264a734 <+0>: sub sp, sp,#0x10 ; =0x10 //开辟一个16字节空间
0x10264a738<+4>: str w0, [sp,#0xc] // w0值放入了栈空间,位置是sp偏移#0xc
0x10264a73c<+8>: str w1, [sp,#0x8] // w1 w0和w1的值放入了栈空间,位置是sp偏移#0x8
-> 0x10264a740<+12>: ldr w8, [sp,#0xc] //把栈空间的值读出来放入寄存器w8
0x10264a744<+16>: ldr w9, [sp,#0x8] //把栈空间的值读出来放入寄存器w9
0x10264a748<+20>: cmp w8, w9 //比较w8,w9
0x10264a74c<+24>: b.le 0x10264a764 //比较结果是小于等于(less than or qeual to),执行标号,否则不跳转
0x10264a750<+28>: ldr w8, [sp,#0xc] //把栈空间的值读出来放入寄存器w8
0x10264a754<+32>: adrp x9,2 // 2左移12位0x10264a000 + 2 0x10264c000
0x10264a758 <+36>: add x9, x9,#0xd88 //0x10264c000 +0xd88 = 0x10264cd88
0x10264a75c<+40>: str w8, [x9] //w9 地址值写个W8
0x10264a760<+44>: b 0x10264a774 //跳转到 0x10264a774
0x10264a764<+48>: ldr w8, [sp,#0x8] //读取 sp 偏移0x8 的地址给w8
0x10264a768<+52>: adrp x9,2 / 2左移12位0x10264a000 + 2 0x10264c000
0x10264a76c <+56>: add x9, x9,#0xd88 //0x10264c000 +0xd88 = 0x10264cd88
0x10264a770<+60>: str w8, [x9] 把x9 的地址给 w8
0x10264a774 <+64>: add sp, sp,#0x10 ; =0x10 //栈平衡
0x10264a778<+68>: ret
Switch
1、假设switch语句的分支比较少的时候(例如3,少于4的时候没有意义)没有必要使用此结构,相当于if。
2、各个分支常量的差值较大的时候,编译器会在效率还是内存进行取舍,这个时候编译器还是会编译成类似于if,else的结构。
3、在分支比较多的时候:在编译的时候会生成一个表(跳转表每个地址四个字节)。
当switch条件小于4个的时候就是if汇编的判断
0x10465a124 <+16>: ldur w8, [x29, #-0x4]
0x10465a128 <+20>: cmp w8, #0x1 ; =0x1
0x10465a12c <+24>: str w8, [sp, #0x8]
0x10465a130 <+28>: b.eq 0x10465a158 ; <+68> at main.m
0x10465a134 <+32>: b 0x10465a138 ; <+36> at main.m
0x10465a138 <+36>: ldr w8, [sp, #0x8]
0x10465a13c <+40>: cmp w8, #0x2 ; =0x2
0x10465a140 <+44>: b.eq 0x10465a168 ; <+84> at main.m
0x10465a144 <+48>: b 0x10465a148 ; <+52> at main.m
0x10465a148 <+52>: ldr w8, [sp, #0x8]
0x10465a14c <+56>: cmp w8, #0x3 ; =0x3
0x10465a150 <+60>: b.eq 0x10465a178 ; <+100> at main.m
0x10465a154 <+64>: b 0x10465a188 ; <+116> at main.m
当条件大于4个
0x10242a100 <+20>: subs w8, w8, #0x1 ; =0x1
0x10242a104 <+24>: mov x9, x8
0x10242a108 <+28>: ubfx x9, x9, #0, #32
0x10242a10c <+32>: cmp x9, #0x4 ; =0x4
0x10242a110 <+36>: str x9, [sp]
0x10242a114 <+40>: b.hi 0x10242a170 ; <+132> at main.m
0x10242a118 <+44>: adrp x8, 0
0x10242a11c <+48>: add x8, x8, #0x188 ; =0x188
0x10242a120 <+52>: ldr x11, [sp]
0x10242a124 <+56>: ldrsw x10, [x8, x11, lsl #2]
0x10242a128 <+60>: add x9, x8, x10
0x10242a12c <+64>: br x9
0x10242a130 <+68>: adrp x0, 1
0x10242a134 <+72>: add x0, x0, #0xf69 ; =0xf69
0x10242a138 <+76>: bl 0x10242a588 ; symbol stub for: printf
0x10242a13c <+80>: b 0x10242a17c
源码
void funcA(int a){
switch (a) {//
case 1:
printf("打坐");
break;
case 2:
printf("加红");
break;
case 3:
printf("加蓝");
break;
case 5:
printf("打怪");
break;
default:
printf("啥都不干");
break;
}
}
汇编代码
0x10242a0ec <+0>: sub sp, sp, #0x20 ; =0x20
0x10242a0f0 <+4>: stp x29, x30, [sp, #0x10]
0x10242a0f4 <+8>: add x29, sp, #0x10 ; =0x10
0x10242a0f8 <+12>: stur w0, [x29, #-0x4]
0x10242a0fc <+16>: ldur w8, [x29, #-0x4]
0x10242a100 <+20>: subs w8, w8, #0x1 ; =0x1
0x10242a104 <+24>: mov x9, x8
0x10242a108 <+28>: ubfx x9, x9, #0, #32
0x10242a10c <+32>: cmp x9, #0x4 ; =0x4
0x10242a110 <+36>: str x9, [sp]
0x10242a114 <+40>: b.hi 0x10242a170 ; <+132> at main.m
0x10242a118 <+44>: adrp x8, 0
0x10242a11c <+48>: add x8, x8, #0x188 ; =0x188
0x10242a120 <+52>: ldr x11, [sp]
0x10242a124 <+56>: ldrsw x10, [x8, x11, lsl #2]
0x10242a128 <+60>: add x9, x8, x10
0x10242a12c <+64>: br x9
0x10242a130 <+68>: adrp x0, 1
0x10242a134 <+72>: add x0, x0, #0xf69 ; =0xf69
0x10242a138 <+76>: bl 0x10242a588 ; symbol stub for: printf
0x10242a13c <+80>: b 0x10242a17c ; <+144> at main.m:30:1
0x10242a140 <+84>: adrp x0, 1
0x10242a144 <+88>: add x0, x0, #0xf70 ; =0xf70
0x10242a148 <+92>: bl 0x10242a588 ; symbol stub for: printf
0x10242a14c <+96>: b 0x10242a17c ; <+144> at main.m:30:1
0x10242a150 <+100>: adrp x0, 1
0x10242a154 <+104>: add x0, x0, #0xf77 ; =0xf77
0x10242a158 <+108>: bl 0x10242a588 ; symbol stub for: printf
0x10242a15c <+112>: b 0x10242a17c ; <+144> at main.m:30:1
0x10242a160 <+116>: adrp x0, 1
0x10242a164 <+120>: add x0, x0, #0xf7e ; =0xf7e
0x10242a168 <+124>: bl 0x10242a588 ; symbol stub for: printf
0x10242a16c <+128>: b 0x10242a17c ; <+144> at main.m:30:1
0x10242a170 <+132>: adrp x0, 1
0x10242a174 <+136>: add x0, x0, #0xf85 ; =0xf85
0x10242a178 <+140>: bl 0x10242a588 ; symbol stub for: printf
0x10242a17c <+144>: ldp x29, x30, [sp, #0x10]
0x10242a180 <+148>: add sp, sp, #0x20 ; =0x20
0x10242a184 <+152>: ret