美文网首页arm汇编学习
ARM64汇编学习笔记四(IF、循环和 Switch)

ARM64汇编学习笔记四(IF、循环和 Switch)

作者: 7c205247047d | 来源:发表于2018-04-27 15:49 被阅读0次

    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 执行效率更高。

    相关文章

      网友评论

        本文标题:ARM64汇编学习笔记四(IF、循环和 Switch)

        本文链接:https://www.haomeiwen.com/subject/vbhmlftx.html