循環(huán)&選擇
cmp(Compare)比較指令
CMP 把一個寄存器的內(nèi)容和另一個寄存器的內(nèi)容或立即數(shù)進(jìn)行比較嘹黔。但不存儲結(jié)果,只是正確的更改標(biāo)志涂身。
一般CMP做完判斷后會進(jìn)行跳轉(zhuǎn)雄卷,后面通常會跟上B指令
BL 標(biāo)號:跳轉(zhuǎn)到標(biāo)號處執(zhí)行
B.LT 標(biāo)號:比價結(jié)果是小于(less than),執(zhí)行標(biāo)號蛤售,否則不跳轉(zhuǎn)
B.LE 標(biāo)號:比較結(jié)果是小于等于(less than or qeual to)丁鹉,執(zhí)行標(biāo)號妒潭,否則不跳轉(zhuǎn)
B.GT 標(biāo)號:比較結(jié)果是大于(greater than),執(zhí)行標(biāo)號鳄炉,否則不跳轉(zhuǎn)
B.GE 標(biāo)號:比較結(jié)果是大于等于(greater than or equal to)杜耙,執(zhí)行標(biāo)號,否則不跳轉(zhuǎn)
B.EQ 標(biāo)號:比較結(jié)果是等于(equal to)拂盯,執(zhí)行標(biāo)號佑女,否則不跳轉(zhuǎn)
B.NE 標(biāo)號:比較結(jié)果是不等于(not equal to),執(zhí)行標(biāo)號谈竿,否則不跳轉(zhuǎn)
B.LS 標(biāo)號:比較結(jié)果是無符號小于等于团驱,執(zhí)行標(biāo)號,否則不跳轉(zhuǎn)
B.LO 標(biāo)號:比較結(jié)果是無符號小于空凸,執(zhí)行標(biāo)號嚎花,否則不跳轉(zhuǎn)
B.HI 標(biāo)號:比較結(jié)果是無符號大于,執(zhí)行標(biāo)號呀洲,否則不跳轉(zhuǎn)
B.HS 標(biāo)號:比較結(jié)果是無符號大于等于紊选,執(zhí)行標(biāo)號,否則不跳轉(zhuǎn)
一.分析if 和全局變量的匯編代碼
0x10264a734 <+0>: sub sp, sp,#0x10 ; =0x10 //開辟一個16字節(jié)空間
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 //比較結(jié)果是小于等于(less than or qeual to)吏夯,執(zhí)行標(biāo)號此蜈,否則不跳轉(zhuǎn)
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 //跳轉(zhuǎn)到 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噪生、假設(shè)switch語句的分支比較少的時候(例如3裆赵,少于4的時候沒有意義)沒有必要使用此結(jié)構(gòu),相當(dāng)于if跺嗽。
2顾瞪、各個分支常量的差值較大的時候,編譯器會在效率還是內(nèi)存進(jìn)行取舍抛蚁,這個時候編譯器還是會編譯成類似于if陈醒,else的結(jié)構(gòu)。
3瞧甩、在分支比較多的時候:在編譯的時候會生成一個表(跳轉(zhuǎn)表每個地址四個字節(jié))钉跷。
當(dāng)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
當(dāng)條件大于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("加藍(lán)");
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