ARM64汇编学习笔记四(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 执行效率更高。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容