汇编:IF、循环和 Switch

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

  1. 假设 switch 内分支比较多的时候,在编译的时候会生成一个表(跳转表每个地址四个字节);
  2. 假设 switch 内分支比较少的时候(例如3,少于4的时候没有意义),就没有必要使用此结构,相当于if...else语句的结构;
  3. 假设 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 执行效率更高。



猜你喜欢

转载自blog.csdn.net/s297165331/article/details/80167509