cmp(Compare)比较指令
cmp:把一个寄存器的内容和另一个寄存器的内容或立即数进行比较。但不存储结果,只是正确的更改标志。
一般 cmp 做完判断后会进行跳转,后面通常会跟上B指令。
- BL 标号:跳转到标号处执行
- B.LT 标号:比较结果是小于(less than),执行标号,否则不跳转;
- B.LE 标号:比较结果是小于等于(less than or equal to),执行标号,否则不跳转;
- B.GT 标号:比较结果是大于(greater than),执行标号,否则不跳转;
- B.GE 标号:比较结果是大于等于(greater than or equal to),执行标号,否则不跳转;
- B.EQ 标号:比较结果是等于,执行标号,否则不跳转;
- B.HI 标号:比较结果是无符号大于,执行标号,否则不跳转;
if...else的识别
- 源码
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
void func(int a,int b){
int temp = 0;
if (a >= b) {
temp = a;
}else{
temp = b;
}
}
int main(int argc, char * argv[]) {
func(10, 20);
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
- func 函数的汇编代码
__text:0000000100006798 ; =============== S U B R O U T I N E =======================================
__text:0000000100006798
__text:0000000100006798
__text:0000000100006798 EXPORT _func
__text:0000000100006798 _func ; CODE XREF: _main+28↓p
__text:0000000100006798
__text:0000000100006798 var_C = -0xC
__text:0000000100006798 var_8 = -8
__text:0000000100006798 var_4 = -4
__text:0000000100006798
__text:0000000100006798 SUB SP, SP, #0x10
__text:000000010000679C STR W0, [SP,#0x10+var_4]
__text:00000001000067A0 STR W1, [SP,#0x10+var_8]
__text:00000001000067A4 STR WZR, [SP,#0x10+var_C]
__text:00000001000067A8 LDR W0, [SP,#0x10+var_4]
__text:00000001000067AC LDR W1, [SP,#0x10+var_8]
__text:00000001000067B0 CMP W0, W1
__text:00000001000067B4 B.LT loc_1000067C4
__text:00000001000067B8 LDR W8, [SP,#0x10+var_4]
__text:00000001000067BC STR W8, [SP,#0x10+var_C]
__text:00000001000067C0 B loc_1000067CC
__text:00000001000067C4 ; ---------------------------------------------------------------------------
__text:00000001000067C4
__text:00000001000067C4 loc_1000067C4 ; CODE XREF: _func+1C↑j
__text:00000001000067C4 LDR W8, [SP,#0x10+var_8]
__text:00000001000067C8 STR W8, [SP,#0x10+var_C]
__text:00000001000067CC
__text:00000001000067CC loc_1000067CC ; CODE XREF: _func+28↑j
__text:00000001000067CC ADD SP, SP, #0x10
__text:00000001000067D0 RET
__text:00000001000067D0 ; End of function _func
汇编代码分析
// 1. 判断条件
__text:00000001000067B0 CMP W0, W1
__text:00000001000067B4 B.LT loc_1000067C4
/*
结合这两句代码表示,判断(CMP) w0 和 w1 的比较结果是否小于。
如果是小于,则执行标号(loc_1000067C4)以下的代码,否则不跳转继续执行下 面的代码。
*/
// 2. 不满足条件不跳转继续执行
__text:00000001000067B8 LDR W8, [SP,#0x10+var_4]
__text:00000001000067BC STR W8, [SP,#0x10+var_C]
// 3. 满足条件跳转标号执行
__text:00000001000067C4 loc_1000067C4 ; CODE XREF: _func+1C↑j
__text:00000001000067C4 LDR W8, [SP,#0x10+var_8]
__text:00000001000067C8 STR W8, [SP,#0x10+var_C]
do…while 循环的识别
- 源码
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
void func() {
int nSum = 0;
int i = 0;
do {
i++;
nSum = nSum + i;
} while (i < 100);
}
int main(int argc, char * argv[]) {
func();
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
- func 函数的汇编代码
__text:00000001000067AC ; =============== S U B R O U T I N E =======================================
__text:00000001000067AC
__text:00000001000067AC
__text:00000001000067AC EXPORT _func
__text:00000001000067AC _func ; CODE XREF: _main+18↓p
__text:00000001000067AC
__text:00000001000067AC var_8 = -8
__text:00000001000067AC var_4 = -4
__text:00000001000067AC
__text:00000001000067AC SUB SP, SP, #0x10
__text:00000001000067B0 STR WZR, [SP,#0x10+var_4]
__text:00000001000067B4 STR WZR, [SP,#0x10+var_8]
__text:00000001000067B8
__text:00000001000067B8 loc_1000067B8 ; CODE XREF: _func+30↓j
__text:00000001000067B8 LDR W8, [SP,#0x10+var_8]
__text:00000001000067BC ADD W8, W8, #1
__text:00000001000067C0 STR W8, [SP,#0x10+var_8]
__text:00000001000067C4 LDR W8, [SP,#0x10+var_4]
__text:00000001000067C8 LDR W9, [SP,#0x10+var_8]
__text:00000001000067CC ADD W8, W8, W9
__text:00000001000067D0 STR W8, [SP,#0x10+var_4]
__text:00000001000067D4 LDR W8, [SP,#0x10+var_8]
__text:00000001000067D8 CMP W8, #0x64
__text:00000001000067DC B.LT loc_1000067B8
__text:00000001000067E0 ADD SP, SP, #0x10
__text:00000001000067E4 RET
__text:00000001000067E4 ; End of function _func
汇编代码分析
// 1. 判断条件
__text:00000001000067D8 CMP W8, #0x64
__text:00000001000067DC B.LT loc_1000067B8
// 2. 满足条件跳转标号执行
__text:00000001000067B8 loc_1000067B8 ; CODE XREF: _func+30↓j
__text:00000001000067B8 LDR W8, [SP,#0x10+var_8]
__text:00000001000067BC ADD W8, W8, #1
__text:00000001000067C0 STR W8, [SP,#0x10+var_8]
__text:00000001000067C4 LDR W8, [SP,#0x10+var_4]
__text:00000001000067C8 LDR W9, [SP,#0x10+var_8]
__text:00000001000067CC ADD W8, W8, W9
__text:00000001000067D0 STR W8, [SP,#0x10+var_4]
__text:00000001000067D4 LDR W8, [SP,#0x10+var_8]
while 循环的识别
- 源码
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
void func() {
int nSum = 0;
int i = 0;
while (i < 100){
i++;
nSum = nSum + i;
}
}
int main(int argc, char * argv[]) {
func();
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
- func 函数的汇编代码
__text:00000001000067A8 ; =============== S U B R O U T I N E =======================================
__text:00000001000067A8
__text:00000001000067A8
__text:00000001000067A8 EXPORT _func
__text:00000001000067A8 _func ; CODE XREF: _main+18↓p
__text:00000001000067A8
__text:00000001000067A8 var_8 = -8
__text:00000001000067A8 var_4 = -4
__text:00000001000067A8
__text:00000001000067A8 SUB SP, SP, #0x10
__text:00000001000067AC STR WZR, [SP,#0x10+var_4]
__text:00000001000067B0 STR WZR, [SP,#0x10+var_8]
__text:00000001000067B4
__text:00000001000067B4 loc_1000067B4 ; CODE XREF: _func+34↓j
__text:00000001000067B4 LDR W8, [SP,#0x10+var_8]
__text:00000001000067B8 CMP W8, #0x64
__text:00000001000067BC B.GE loc_1000067E0
__text:00000001000067C0 LDR W8, [SP,#0x10+var_8]
__text:00000001000067C4 ADD W8, W8, #1
__text:00000001000067C8 STR W8, [SP,#0x10+var_8]
__text:00000001000067CC LDR W8, [SP,#0x10+var_4]
__text:00000001000067D0 LDR W9, [SP,#0x10+var_8]
__text:00000001000067D4 ADD W8, W8, W9
__text:00000001000067D8 STR W8, [SP,#0x10+var_4]
__text:00000001000067DC B loc_1000067B4
__text:00000001000067E0 ; ---------------------------------------------------------------------------
__text:00000001000067E0
__text:00000001000067E0 loc_1000067E0 ; CODE XREF: _func+14↑j
__text:00000001000067E0 ADD SP, SP, #0x10
__text:00000001000067E4 RET
__text:00000001000067E4 ; End of function _func
汇编代码分析
// 1. 判断条件是否满足
__text:00000001000067B4 loc_1000067B4 ; CODE XREF: _func+34↓j
__text:00000001000067B4 LDR W8, [SP,#0x10+var_8]
__text:00000001000067B8 CMP W8, #0x64
__text:00000001000067BC B.GE loc_1000067E0
// 2.条件满足则继续执行,执行完最后一句代码之后,又执行第一步,直到条件不满足后再跳出循环
__text:00000001000067C0 LDR W8, [SP,#0x10+var_8]
__text:00000001000067C4 ADD W8, W8, #1
__text:00000001000067C8 STR W8, [SP,#0x10+var_8]
__text:00000001000067CC LDR W8, [SP,#0x10+var_4]
__text:00000001000067D0 LDR W9, [SP,#0x10+var_8]
__text:00000001000067D4 ADD W8, W8, W9
__text:00000001000067D8 STR W8, [SP,#0x10+var_4]
__text:00000001000067DC B loc_1000067B4
for 循环的识别
- 源码
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
void func() {
for (int i = 0; i < 100; i++) {
printf("hello");
}
}
int main(int argc, char * argv[]) {
func();
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
- func 函数的汇编代码
__text:000000010000678C ; =============== S U B R O U T I N E =======================================
__text:000000010000678C
__text:000000010000678C ; Attributes: bp-based frame
__text:000000010000678C
__text:000000010000678C EXPORT _func
__text:000000010000678C _func ; CODE XREF: _main+18↓p
__text:000000010000678C
__text:000000010000678C var_8 = -8
__text:000000010000678C var_4 = -4
__text:000000010000678C var_s0 = 0
__text:000000010000678C
__text:000000010000678C SUB SP, SP, #0x20
__text:0000000100006790 STP X29, X30, [SP,#0x10+var_s0]
__text:0000000100006794 ADD X29, SP, #0x10
__text:0000000100006798 STUR WZR, [X29,#var_4]
__text:000000010000679C
__text:000000010000679C loc_10000679C ; CODE XREF: _func+38↓j
__text:000000010000679C LDUR W8, [X29,#var_4]
__text:00000001000067A0 CMP W8, #0x64
__text:00000001000067A4 B.GE loc_1000067C8
__text:00000001000067A8 ADRP X0, #aHello@PAGE ; "hello"
__text:00000001000067AC ADD X0, X0, #aHello@PAGEOFF ; "hello"
__text:00000001000067B0 BL _printf
__text:00000001000067B4 STR W0, [SP,#0x10+var_8]
__text:00000001000067B8 LDUR W8, [X29,#var_4]
__text:00000001000067BC ADD W8, W8, #1
__text:00000001000067C0 STUR W8, [X29,#var_4]
__text:00000001000067C4 B loc_10000679C
__text:00000001000067C8 ; ---------------------------------------------------------------------------
__text:00000001000067C8
__text:00000001000067C8 loc_1000067C8 ; CODE XREF: _func+18↑j
__text:00000001000067C8 LDP X29, X30, [SP,#0x10+var_s0]
__text:00000001000067CC ADD SP, SP, #0x20
__text:00000001000067D0 RET
__text:00000001000067D0 ; End of function _func
汇编代码分析
通过与 while 的汇编代码对比,可以得知类似于 while 循环语句。
Switch
- 假设 switch 内分支比较多的时候,在编译的时候会生成一个表(跳转表每个地址四个字节);
- 假设 switch 内分支比较少的时候(例如3,少于4的时候没有意义),就没有必要使用此结构,相当于if...else语句的结构;
- 假设 switch 内各个分支常量的差值较大的时候,编译器会在效率还是内存之间进行取舍,如果效率优先的情况下,这个时候编译器还是会编译成类似于if..else的结构。
-
Switch 内分支少于4的情况下:
源码
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
void func(int a) {
switch (a) {
case 1:
printf("上路");
break;
case 2:
printf("中路");
break;
case 3:
printf("下路");
break;
default:
printf("随机匹配");
break;
}
}
int main(int argc, char * argv[]) {
func(1);
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
汇编代码
__text:0000000100006704 ; =============== S U B R O U T I N E =======================================
__text:0000000100006704
__text:0000000100006704 ; Attributes: bp-based frame
__text:0000000100006704
__text:0000000100006704 EXPORT _func
__text:0000000100006704 _func ; CODE XREF: _main+20↓p
__text:0000000100006704
__text:0000000100006704 var_24 = -0x24
__text:0000000100006704 var_20 = -0x20
__text:0000000100006704 var_1C = -0x1C
__text:0000000100006704 var_18 = -0x18
__text:0000000100006704 var_14 = -0x14
__text:0000000100006704 var_10 = -0x10
__text:0000000100006704 var_C = -0xC
__text:0000000100006704 var_8 = -8
__text:0000000100006704 var_4 = -4
__text:0000000100006704 var_s0 = 0
__text:0000000100006704
__text:0000000100006704 SUB SP, SP, #0x40
__text:0000000100006708 STP X29, X30, [SP,#0x30+var_s0]
__text:000000010000670C ADD X29, SP, #0x30
__text:0000000100006710 STUR W0, [X29,#var_4]
__text:0000000100006714 LDUR W0, [X29,#var_4]
__text:0000000100006718 MOV X8, X0
__text:000000010000671C SUBS W0, W0, #1
__text:0000000100006720 STUR W8, [X29,#var_8]
__text:0000000100006724 STUR W0, [X29,#var_C]
__text:0000000100006728 B.EQ loc_100006758
__text:000000010000672C B loc_100006730
__text:0000000100006730 ; ---------------------------------------------------------------------------
__text:0000000100006730
__text:0000000100006730 loc_100006730 ; CODE XREF: _func+28↑j
__text:0000000100006730 LDUR W8, [X29,#var_8]
__text:0000000100006734 SUBS W9, W8, #2
__text:0000000100006738 STUR W9, [X29,#var_10]
__text:000000010000673C B.EQ loc_10000676C
__text:0000000100006740 B loc_100006744
__text:0000000100006744 ; ---------------------------------------------------------------------------
__text:0000000100006744
__text:0000000100006744 loc_100006744 ; CODE XREF: _func+3C↑j
__text:0000000100006744 LDUR W8, [X29,#var_8]
__text:0000000100006748 SUBS W9, W8, #3
__text:000000010000674C STUR W9, [X29,#var_14]
__text:0000000100006750 B.EQ loc_100006780
__text:0000000100006754 B loc_100006794
__text:0000000100006758 ; ---------------------------------------------------------------------------
__text:0000000100006758
__text:0000000100006758 loc_100006758 ; CODE XREF: _func+24↑j
__text:0000000100006758 ADRP X0, #asc_100007F10@PAGE ; "上路"
__text:000000010000675C ADD X0, X0, #asc_100007F10@PAGEOFF ; "上路"
__text:0000000100006760 BL _printf
__text:0000000100006764 STR W0, [SP,#0x30+var_18]
__text:0000000100006768 B loc_1000067A4
__text:000000010000676C ; ---------------------------------------------------------------------------
__text:000000010000676C
__text:000000010000676C loc_10000676C ; CODE XREF: _func+38↑j
__text:000000010000676C ADRP X0, #asc_100007F17@PAGE ; "中路"
__text:0000000100006770 ADD X0, X0, #asc_100007F17@PAGEOFF ; "中路"
__text:0000000100006774 BL _printf
__text:0000000100006778 STR W0, [SP,#0x30+var_1C]
__text:000000010000677C B loc_1000067A4
__text:0000000100006780 ; ---------------------------------------------------------------------------
__text:0000000100006780
__text:0000000100006780 loc_100006780 ; CODE XREF: _func+4C↑j
__text:0000000100006780 ADRP X0, #asc_100007F1E@PAGE ; "下路"
__text:0000000100006784 ADD X0, X0, #asc_100007F1E@PAGEOFF ; "下路"
__text:0000000100006788 BL _printf
__text:000000010000678C STR W0, [SP,#0x30+var_20]
__text:0000000100006790 B loc_1000067A4
__text:0000000100006794 ; ---------------------------------------------------------------------------
__text:0000000100006794
__text:0000000100006794 loc_100006794 ; CODE XREF: _func+50↑j
__text:0000000100006794 ADRP X0, #asc_100007F25@PAGE ; "随机匹配"
__text:0000000100006798 ADD X0, X0, #asc_100007F25@PAGEOFF ; "随机匹配"
__text:000000010000679C BL _printf
__text:00000001000067A0 STR W0, [SP,#0x30+var_24]
__text:00000001000067A4
__text:00000001000067A4 loc_1000067A4 ; CODE XREF: _func+64↑j
__text:00000001000067A4 ; _func+78↑j ...
__text:00000001000067A4 LDP X29, X30, [SP,#0x30+var_s0]
__text:00000001000067A8 ADD SP, SP, #0x40
__text:00000001000067AC RET
__text:00000001000067AC ; End of function _func
汇编代码分析
通过与 if...else 的汇编代码对比,可以得知类似于 if...else 条件判断语句。
-
Switch 内分支大于等于4的情况下:
源码
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
void func(int a) {
switch (a) {
case 1:
printf("上路");
break;
case 2:
printf("中路");
break;
case 3:
printf("下路");
break;
case 4:
printf("野区");
break;
default:
printf("随机匹配");
break;
}
}
int main(int argc, char * argv[]) {
func(1);
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
汇编代码
__text:00000001000066E8 ; =============== S U B R O U T I N E =======================================
__text:00000001000066E8
__text:00000001000066E8 ; Attributes: bp-based frame
__text:00000001000066E8
__text:00000001000066E8 EXPORT _func
__text:00000001000066E8 _func ; CODE XREF: _main+20↓p
__text:00000001000066E8
__text:00000001000066E8 var_28 = -0x28
__text:00000001000066E8 var_24 = -0x24
__text:00000001000066E8 var_20 = -0x20
__text:00000001000066E8 var_1C = -0x1C
__text:00000001000066E8 var_18 = -0x18
__text:00000001000066E8 var_14 = -0x14
__text:00000001000066E8 var_10 = -0x10
__text:00000001000066E8 var_4 = -4
__text:00000001000066E8 var_s0 = 0
__text:00000001000066E8
__text:00000001000066E8 SUB SP, SP, #0x40
__text:00000001000066EC STP X29, X30, [SP,#0x30+var_s0]
__text:00000001000066F0 ADD X29, SP, #0x30
__text:00000001000066F4 STUR W0, [X29,#var_4]
__text:00000001000066F8 LDUR W0, [X29,#var_4]
__text:00000001000066FC SUBS W0, W0, #1 ; switch 4 cases
__text:0000000100006700 MOV X8, X0
__text:0000000100006704 SUBS W0, W0, #3
__text:0000000100006708 STUR X8, [X29,#var_10]
__text:000000010000670C STUR W0, [X29,#var_14]
__text:0000000100006710 B.HI def_100006728 ; jumptable 0000000100006728 default case
__text:0000000100006714 ADRP X8, #jpt_100006728@PAGE
__text:0000000100006718 ADD X8, X8, #jpt_100006728@PAGEOFF
__text:000000010000671C LDUR X9, [X29,#var_10]
__text:0000000100006720 LDRSW X10, [X8,X9,LSL#2]
__text:0000000100006724 ADD X8, X10, X8
__text:0000000100006728 BR X8 ; switch jump
__text:000000010000672C ; ---------------------------------------------------------------------------
__text:000000010000672C
__text:000000010000672C loc_10000672C ; CODE XREF: _func+40↑j
__text:000000010000672C ; DATA XREF: __text:jpt_100006728↓o
__text:000000010000672C ADRP X0, #asc_100007F08@PAGE ; jumptable 0000000100006728 case 1
__text:0000000100006730 ADD X0, X0, #asc_100007F08@PAGEOFF ; "上路"
__text:0000000100006734 BL _printf
__text:0000000100006738 STR W0, [SP,#0x30+var_18]
__text:000000010000673C B loc_10000678C
__text:0000000100006740 ; ---------------------------------------------------------------------------
__text:0000000100006740
__text:0000000100006740 loc_100006740 ; CODE XREF: _func+40↑j
__text:0000000100006740 ; DATA XREF: __text:000000010000679C↓o
__text:0000000100006740 ADRP X0, #asc_100007F0F@PAGE ; jumptable 0000000100006728 case 2
__text:0000000100006744 ADD X0, X0, #asc_100007F0F@PAGEOFF ; "中路"
__text:0000000100006748 BL _printf
__text:000000010000674C STR W0, [SP,#0x30+var_1C]
__text:0000000100006750 B loc_10000678C
__text:0000000100006754 ; ---------------------------------------------------------------------------
__text:0000000100006754
__text:0000000100006754 loc_100006754 ; CODE XREF: _func+40↑j
__text:0000000100006754 ; DATA XREF: __text:00000001000067A0↓o
__text:0000000100006754 ADRP X0, #asc_100007F16@PAGE ; jumptable 0000000100006728 case 3
__text:0000000100006758 ADD X0, X0, #asc_100007F16@PAGEOFF ; "下路"
__text:000000010000675C BL _printf
__text:0000000100006760 STR W0, [SP,#0x30+var_20]
__text:0000000100006764 B loc_10000678C
__text:0000000100006768 ; ---------------------------------------------------------------------------
__text:0000000100006768
__text:0000000100006768 loc_100006768 ; CODE XREF: _func+40↑j
__text:0000000100006768 ; DATA XREF: __text:00000001000067A4↓o
__text:0000000100006768 ADRP X0, #asc_100007F1D@PAGE ; jumptable 0000000100006728 case 4
__text:000000010000676C ADD X0, X0, #asc_100007F1D@PAGEOFF ; "野区"
__text:0000000100006770 BL _printf
__text:0000000100006774 STR W0, [SP,#0x30+var_24]
__text:0000000100006778 B loc_10000678C
__text:000000010000677C ; ---------------------------------------------------------------------------
__text:000000010000677C
__text:000000010000677C def_100006728 ; CODE XREF: _func+28↑j
__text:000000010000677C ADRP X0, #asc_100007F24@PAGE ; jumptable 0000000100006728 default case
__text:0000000100006780 ADD X0, X0, #asc_100007F24@PAGEOFF ; "随机匹配"
__text:0000000100006784 BL _printf
__text:0000000100006788 STR W0, [SP,#0x30+var_28]
__text:000000010000678C
__text:000000010000678C loc_10000678C ; CODE XREF: _func+54↑j
__text:000000010000678C ; _func+68↑j ...
__text:000000010000678C LDP X29, X30, [SP,#0x30+var_s0]
__text:0000000100006790 ADD SP, SP, #0x40
__text:0000000100006794 RET
__text:0000000100006794 ; End of function _func
汇编代码分析
__text:00000001000066F4 STUR W0, [X29,#var_4]
__text:00000001000066F8 LDUR W0, [X29,#var_4]
__text:00000001000066FC SUBS W0, W0, #1 ; switch 4 cases
__text:0000000100006700 MOV X8, X0
__text:0000000100006704 SUBS W0, W0, #3
__text:0000000100006708 STUR X8, [X29,#var_10]
__text:000000010000670C STUR W0, [X29,#var_14]
__text:0000000100006710 B.HI def_100006728 ; jumptable 0000000100006728 default case
__text:0000000100006714 ADRP X8, #jpt_100006728@PAGE
__text:0000000100006718 ADD X8, X8, #jpt_100006728@PAGEOFF
__text:000000010000671C LDUR X9, [X29,#var_10]
__text:0000000100006720 LDRSW X10, [X8,X9,LSL#2]
__text:0000000100006724 ADD X8, X10, X8
__text:0000000100006728 BR X8 ; switch jump
//
1. switch 内分支比较多的时候,在编译的时候会生成一个表(跳转表每个地址四个字节);
2. 先判断是否是 default 分支;// B.HI def_100006728
3. 取 X8的地址;
ADRP X8, #jpt_100006728@PAGE
ADD X8, X8, #jpt_100006728@PAGEOFF
// ADRP + ADD表示取值,常用于取常量和全局变量的值,但是这里取的是地址值。
LDUR X9, [X29,#var_10]
LDRSW X10, [X8,X9,LSL#2]
// LDRSW
// [X8,X9,LSL#2] 表示以 X8 为基地址,X9的二进制左移2位,再相加得到一个新的地址值。
// 例如:A表示(X8 为基地址),B 表示(X9的二进制左移2位)
// 那么 X10 = [A B];
ADD X8, X10, X8
// X8 = X10 和 X8的值相加
通过这一系列的运行最后得到即将要跳转地址值X8,这种方式的计算效率非常高,只需要一次算法,就能找到 X8 的地址。
4. 跳转到X8的地址;
BR X8 ; switch jump
// 跳转到 X8为标号的地址执行
-
Switch 内各个分支常量的差值较大的情况下:
源码
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
void func(int a) {
switch (a) {
case 10:
printf("上路");
break;
case 102:
printf("中路");
break;
case 700:
printf("下路");
break;
case 24:
printf("野区");
break;
default:
printf("随机匹配");
break;
}
}
int main(int argc, char * argv[]) {
func(1);
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
汇编代码
__text:00000001000066D4 ; =============== S U B R O U T I N E =======================================
__text:00000001000066D4
__text:00000001000066D4 ; Attributes: bp-based frame
__text:00000001000066D4
__text:00000001000066D4 EXPORT _func
__text:00000001000066D4 _func ; CODE XREF: _main+20↓p
__text:00000001000066D4
__text:00000001000066D4 var_2C = -0x2C
__text:00000001000066D4 var_28 = -0x28
__text:00000001000066D4 var_24 = -0x24
__text:00000001000066D4 var_20 = -0x20
__text:00000001000066D4 var_1C = -0x1C
__text:00000001000066D4 var_18 = -0x18
__text:00000001000066D4 var_14 = -0x14
__text:00000001000066D4 var_10 = -0x10
__text:00000001000066D4 var_C = -0xC
__text:00000001000066D4 var_8 = -8
__text:00000001000066D4 var_4 = -4
__text:00000001000066D4 var_s0 = 0
__text:00000001000066D4
__text:00000001000066D4 SUB SP, SP, #0x40
__text:00000001000066D8 STP X29, X30, [SP,#0x30+var_s0]
__text:00000001000066DC ADD X29, SP, #0x30
__text:00000001000066E0 STUR W0, [X29,#var_4]
__text:00000001000066E4 LDUR W0, [X29,#var_4]
__text:00000001000066E8 MOV X8, X0
__text:00000001000066EC SUBS W0, W0, #0xA
__text:00000001000066F0 STUR W8, [X29,#var_8]
__text:00000001000066F4 STUR W0, [X29,#var_C]
__text:00000001000066F8 B.EQ loc_10000673C
__text:00000001000066FC B loc_100006700
__text:0000000100006700 ; ---------------------------------------------------------------------------
__text:0000000100006700
__text:0000000100006700 loc_100006700 ; CODE XREF: _func+28↑j
__text:0000000100006700 LDUR W8, [X29,#var_8]
__text:0000000100006704 SUBS W9, W8, #0x18
__text:0000000100006708 STUR W9, [X29,#var_10]
__text:000000010000670C B.EQ loc_100006778
__text:0000000100006710 B loc_100006714
__text:0000000100006714 ; ---------------------------------------------------------------------------
__text:0000000100006714
__text:0000000100006714 loc_100006714 ; CODE XREF: _func+3C↑j
__text:0000000100006714 LDUR W8, [X29,#var_8]
__text:0000000100006718 SUBS W9, W8, #0x66
__text:000000010000671C STUR W9, [X29,#var_14]
__text:0000000100006720 B.EQ loc_100006750
__text:0000000100006724 B loc_100006728
__text:0000000100006728 ; ---------------------------------------------------------------------------
__text:0000000100006728
__text:0000000100006728 loc_100006728 ; CODE XREF: _func+50↑j
__text:0000000100006728 LDUR W8, [X29,#var_8]
__text:000000010000672C SUBS W9, W8, #0x2BC
__text:0000000100006730 STR W9, [SP,#0x30+var_18]
__text:0000000100006734 B.EQ loc_100006764
__text:0000000100006738 B loc_10000678C
__text:000000010000673C ; ---------------------------------------------------------------------------
__text:000000010000673C
__text:000000010000673C loc_10000673C ; CODE XREF: _func+24↑j
__text:000000010000673C ADRP X0, #asc_100007F08@PAGE ; "上路"
__text:0000000100006740 ADD X0, X0, #asc_100007F08@PAGEOFF ; "上路"
__text:0000000100006744 BL _printf
__text:0000000100006748 STR W0, [SP,#0x30+var_1C]
__text:000000010000674C B loc_10000679C
__text:0000000100006750 ; ---------------------------------------------------------------------------
__text:0000000100006750
__text:0000000100006750 loc_100006750 ; CODE XREF: _func+4C↑j
__text:0000000100006750 ADRP X0, #asc_100007F0F@PAGE ; "中路"
__text:0000000100006754 ADD X0, X0, #asc_100007F0F@PAGEOFF ; "中路"
__text:0000000100006758 BL _printf
__text:000000010000675C STR W0, [SP,#0x30+var_20]
__text:0000000100006760 B loc_10000679C
__text:0000000100006764 ; ---------------------------------------------------------------------------
__text:0000000100006764
__text:0000000100006764 loc_100006764 ; CODE XREF: _func+60↑j
__text:0000000100006764 ADRP X0, #asc_100007F16@PAGE ; "下路"
__text:0000000100006768 ADD X0, X0, #asc_100007F16@PAGEOFF ; "下路"
__text:000000010000676C BL _printf
__text:0000000100006770 STR W0, [SP,#0x30+var_24]
__text:0000000100006774 B loc_10000679C
__text:0000000100006778 ; ---------------------------------------------------------------------------
__text:0000000100006778
__text:0000000100006778 loc_100006778 ; CODE XREF: _func+38↑j
__text:0000000100006778 ADRP X0, #asc_100007F1D@PAGE ; "野区"
__text:000000010000677C ADD X0, X0, #asc_100007F1D@PAGEOFF ; "野区"
__text:0000000100006780 BL _printf
__text:0000000100006784 STR W0, [SP,#0x30+var_28]
__text:0000000100006788 B loc_10000679C
__text:000000010000678C ; ---------------------------------------------------------------------------
__text:000000010000678C
__text:000000010000678C loc_10000678C ; CODE XREF: _func+64↑j
__text:000000010000678C ADRP X0, #asc_100007F24@PAGE ; "随机匹配"
__text:0000000100006790 ADD X0, X0, #asc_100007F24@PAGEOFF ; "随机匹配"
__text:0000000100006794 BL _printf
__text:0000000100006798 STR W0, [SP,#0x30+var_2C]
__text:000000010000679C
__text:000000010000679C loc_10000679C ; CODE XREF: _func+78↑j
__text:000000010000679C ; _func+8C↑j ...
__text:000000010000679C LDP X29, X30, [SP,#0x30+var_s0]
__text:00000001000067A0 ADD SP, SP, #0x40
__text:00000001000067A4 RET
__text:00000001000067A4 ; End of function _func
汇编代码分析
通过与 if...else 的汇编代码对比,可以得知类似于 if...else 条件判断语句。
小结:
在使用 switch语句 和 if...else语句执行效率高低的问题,是可以通过汇编代码得出结论:
当 switch 分支和 if...else的条件判断小于4的时候,执行效率是一样的;
当 switch 分支和 if...else的条件判断大于等于4的时候,switch 执行效率更高。