美文网首页
[arm64]4、循环&选择

[arm64]4、循环&选择

作者: 史记_d5da | 来源:发表于2021-12-12 00:43 被阅读0次

    1、cmp(Compare)比较指令

    CMP 把一个寄存器的内容和另一个寄存器的内容或立即数进行比较。但不存储结果,只是正确的更改标志。
    一般CMP做完判断后会进行跳转,后面通常会跟上B指令!

    • BL 标号:跳转到标号处执行
    • B.GT 标号:比较结果是大于(greater than),执行标号,否则不跳转
    • B.GE 标号:比较结果是大于等于(greater than or equal to),执行标号,否则不跳转
    • B.EQ 标号:比较结果是等于,执行标号,否则不跳转
    • B.HI 标号:比较结果是无符号大于,执行标号,否则不跳转
    1.1、if条件判断
    int g = 12;
    void func(int a,int b){
        if (a > b) {
            g = a;
        }else{
            g = b;
        }
    }
    int main(int argc, char * argv[]) {
        func(1, 2);
        return 0;
    }
    

    func汇编

    002--if的识别`func:
        0x10419dfec <+0>:  sub    sp, sp, #0x10             ; =0x10 
    ->  0x10419dff0 <+4>:  str    w0, [sp, #0xc]
        0x10419dff4 <+8>:  str    w1, [sp, #0x8]
        0x10419dff8 <+12>: ldr    w8, [sp, #0xc]
        0x10419dffc <+16>: ldr    w9, [sp, #0x8]
        0x10419e000 <+20>: subs   w8, w8, w9
        0x10419e004 <+24>: b.le   0x10419e018               ; <+44> at main.m:17:13
        0x10419e008 <+28>: ldr    w8, [sp, #0xc]
        0x10419e00c <+32>: adrp   x9, 7
        0x10419e010 <+36>: str    w8, [x9, #0x498]
        0x10419e014 <+40>: b      0x10419e024               ; <+56> at main.m:19:1
        0x10419e018 <+44>: ldr    w8, [sp, #0x8]
        0x10419e01c <+48>: adrp   x9, 7
        0x10419e020 <+52>: str    w8, [x9, #0x498]
        0x10419e024 <+56>: add    sp, sp, #0x10             ; =0x10 
        0x10419e028 <+60>: ret    
    
    1.2、do while循环

    判断条件b.lt

    void func() {
        int nSum = 0;
        int i = 0;
        do {
            nSum = nSum + 1;
            i ++;
        } while (i < 100);
    }
    

    汇编代码

    003--Loop`func:
    ->  0x1007fdf6c <+0>:  sub    sp, sp, #0x10             ; =0x10 
        0x1007fdf70 <+4>:  str    wzr, [sp, #0xc]
        0x1007fdf74 <+8>:  str    wzr, [sp, #0x8]
    // do while 循环
        0x1007fdf78 <+12>: ldr    w8, [sp, #0xc]
        0x1007fdf7c <+16>: add    w8, w8, #0x1              ; =0x1 
        0x1007fdf80 <+20>: str    w8, [sp, #0xc]
        0x1007fdf84 <+24>: ldr    w8, [sp, #0x8]
        0x1007fdf88 <+28>: add    w8, w8, #0x1              ; =0x1 
        0x1007fdf8c <+32>: str    w8, [sp, #0x8]
        0x1007fdf90 <+36>: ldr    w8, [sp, #0x8]
    // 与100 比较
        0x1007fdf94 <+40>: subs   w8, w8, #0x64             ; =0x64 
        0x1007fdf98 <+44>: b.lt   0x1007fdf78               ; <+12> at main.m:14:16
        0x1007fdf9c <+48>: add    sp, sp, #0x10             ; =0x10 
        0x1007fdfa0 <+52>: ret 
    
    1.3、while循环

    判断条件b.ge

    void func() {
        int nSum = 0;
        int i = 0;
        while (i < 100) {
            nSum = nSum + 1;
            i++;
        }
    }
    

    汇编代码

    003--Loop`func:
    ->  0x100c65f68 <+0>:  sub    sp, sp, #0x10             ; =0x10 
        0x100c65f6c <+4>:  str    wzr, [sp, #0xc]
        0x100c65f70 <+8>:  str    wzr, [sp, #0x8]
        0x100c65f74 <+12>: ldr    w8, [sp, #0x8]
    // 与100 比较 while循环
        0x100c65f78 <+16>: subs   w8, w8, #0x64             ; =0x64 
        0x100c65f7c <+20>: b.ge   0x100c65f9c               ; <+52> at main.m:17:1
        0x100c65f80 <+24>: ldr    w8, [sp, #0xc]
        0x100c65f84 <+28>: add    w8, w8, #0x1              ; =0x1 
        0x100c65f88 <+32>: str    w8, [sp, #0xc]
        0x100c65f8c <+36>: ldr    w8, [sp, #0x8]
        0x100c65f90 <+40>: add    w8, w8, #0x1              ; =0x1 
        0x100c65f94 <+44>: str    w8, [sp, #0x8]
        0x100c65f98 <+48>: b      0x100c65f74               ; <+12> at main.m:13:12
    // 循环结束
        0x100c65f9c <+52>: add    sp, sp, #0x10             ; =0x10 
        0x100c65fa0 <+56>: ret    
    
    1.4、for 循环

    for 循环和while循环相似

    2、Switch

    1、假设switch语句的分支比较少的时候(例如3,少于4的时候没有意义)没有必要使用此结构,相当于if。
    2、各个分支常量的差值较大的时候,编译器会在效率还是内存进行取舍,这个时候编译器还是会编译成类似于if,else的结构。
    3、在分支比较多的时候:在编译的时候会生成一个表(跳转表每个地址四个字节)。

    2.1、case条件为三个的时候
    void funcA(int a){
        switch (a) {
            case 1:
                printf("1");
                break;
            case 2:
                printf("2");
                break;
            case 3:
                printf("3");
                break;
            default:
                printf("0");
                break;
        }
    }
    

    对应汇编代码

    004--选择`funcA:
    ->  0x100255eec <+0>:   sub    sp, sp, #0x20             ; =0x20 
        0x100255ef0 <+4>:   stp    x29, x30, [sp, #0x10]
        0x100255ef4 <+8>:   add    x29, sp, #0x10            ; =0x10 
        0x100255ef8 <+12>:  stur   w0, [x29, #-0x4]
        0x100255efc <+16>:  ldur   w8, [x29, #-0x4]
        0x100255f00 <+20>:  str    w8, [sp, #0x8]
        0x100255f04 <+24>:  subs   w8, w8, #0x1              ; =0x1 
    // case 1
        0x100255f08 <+28>:  b.eq   0x100255f28               ; <+60> at main.m
        0x100255f0c <+32>:  ldr    w8, [sp, #0x8]
        0x100255f10 <+36>:  subs   w8, w8, #0x2              ; =0x2 
    // case 2
        0x100255f14 <+40>:  b.eq   0x100255f38               ; <+76> at main.m
        0x100255f18 <+44>:  ldr    w8, [sp, #0x8]
        0x100255f1c <+48>:  subs   w8, w8, #0x3              ; =0x3 
    // case 3
        0x100255f20 <+52>:  b.eq   0x100255f48               ; <+92> at main.m
        0x100255f24 <+56>:  b      0x100255f58               ; <+108> at main.m
        0x100255f28 <+60>:  adrp   x0, 2
        0x100255f2c <+64>:  add    x0, x0, #0xe0f            ; =0xe0f 
        0x100255f30 <+68>:  bl     0x100256310               ; symbol stub for: printf
        0x100255f34 <+72>:  b      0x100255f64               ; <+120> at main.m:30:1
        0x100255f38 <+76>:  adrp   x0, 2
        0x100255f3c <+80>:  add    x0, x0, #0xe16            ; =0xe16 
        0x100255f40 <+84>:  bl     0x100256310               ; symbol stub for: printf
        0x100255f44 <+88>:  b      0x100255f64               ; <+120> at main.m:30:1
        0x100255f48 <+92>:  adrp   x0, 2
        0x100255f4c <+96>:  add    x0, x0, #0xe1d            ; =0xe1d 
        0x100255f50 <+100>: bl     0x100256310               ; symbol stub for: printf
        0x100255f54 <+104>: b      0x100255f64               ; <+120> at main.m:30:1
        0x100255f58 <+108>: adrp   x0, 2
        0x100255f5c <+112>: add    x0, x0, #0xe24            ; =0xe24 
        0x100255f60 <+116>: bl     0x100256310               ; symbol stub for: printf
        0x100255f64 <+120>: ldp    x29, x30, [sp, #0x10]
        0x100255f68 <+124>: add    sp, sp, #0x20             ; =0x20 
        0x100255f6c <+128>: ret    
    
    2.2、case大于3个

    1、现将参数,减去最新case
    2、通过表直接映射到具体的case

    void funcA(int a){
        switch (a) {//
            case 1:
                printf("a");
                break;
            case 2:
                printf("b");
                break;
            case 3:
                printf("c");
                break;
            case 5:
                printf("d");
                break;
                
            default:
                printf("0");
                break;
        }
    }
    funcA(4);
    

    对应的汇编代码

    004--选择`funcA:
        0x100a2deb4 <+0>:   sub    sp, sp, #0x20             ; =0x20 
        0x100a2deb8 <+4>:   stp    x29, x30, [sp, #0x10]
        0x100a2debc <+8>:   add    x29, sp, #0x10            ; =0x10 
        0x100a2dec0 <+12>:  stur   w0, [x29, #-0x4]
        0x100a2dec4 <+16>:  ldur   w8, [x29, #-0x4]
        0x100a2dec8 <+20>:  subs   w8, w8, #0x1              ; =0x1 
        0x100a2decc <+24>:  str    x8, [sp]
        0x100a2ded0 <+28>:  subs   x8, x8, #0x4              ; =0x4 
        0x100a2ded4 <+32>:  b.hi   0x100a2df34               ; <+128> at main.m
    // 开始查表
        0x100a2ded8 <+36>:  ldr    x11, [sp]
        0x100a2dedc <+40>:  adrp   x10, 0
        0x100a2dee0 <+44>:  add    x10, x10, #0xf4c          ; =0xf4c 
        0x100a2dee4 <+48>:  adr    x8, #0x0                  ; <+48> at main.m:12:5
        0x100a2dee8 <+52>:  ldrsw  x9, [x10, x11, lsl #2]
    ->  0x100a2deec <+56>:  add    x8, x8, x9
    // 获取跳转地址br
        0x100a2def0 <+60>:  br     x8
        0x100a2def4 <+64>:  adrp   x0, 2
        0x100a2def8 <+68>:  add    x0, x0, #0xdff            ; =0xdff 
        0x100a2defc <+72>:  bl     0x100a2e300               ; symbol stub for: printf
        0x100a2df00 <+76>:  b      0x100a2df40               ; <+140> at main.m:30:1
        0x100a2df04 <+80>:  adrp   x0, 2
        0x100a2df08 <+84>:  add    x0, x0, #0xe06            ; =0xe06 
        0x100a2df0c <+88>:  bl     0x100a2e300               ; symbol stub for: printf
        0x100a2df10 <+92>:  b      0x100a2df40               ; <+140> at main.m:30:1
        0x100a2df14 <+96>:  adrp   x0, 2
        0x100a2df18 <+100>: add    x0, x0, #0xe0d            ; =0xe0d 
        0x100a2df1c <+104>: bl     0x100a2e300               ; symbol stub for: printf
        0x100a2df20 <+108>: b      0x100a2df40               ; <+140> at main.m:30:1
        0x100a2df24 <+112>: adrp   x0, 2
        0x100a2df28 <+116>: add    x0, x0, #0xe14            ; =0xe14 
        0x100a2df2c <+120>: bl     0x100a2e300               ; symbol stub for: printf
        0x100a2df30 <+124>: b      0x100a2df40               ; <+140> at main.m:30:1
        0x100a2df34 <+128>: adrp   x0, 2
        0x100a2df38 <+132>: add    x0, x0, #0xe1b            ; =0xe1b 
        0x100a2df3c <+136>: bl     0x100a2e300               ; symbol stub for: printf
        0x100a2df40 <+140>: ldp    x29, x30, [sp, #0x10]
        0x100a2df44 <+144>: add    sp, sp, #0x20             ; =0x20 
        0x100a2df48 <+148>: ret    
    

    ldrsw指令

    ldrsw x9, [x10, x11, lsl #2]
    新的地址值 = x10的地址值 + (x11的值左移两位)
    x9 = 取出新的地址值所指向的内容

    adrp指令

    0x104089f34 <+128>: adrp x0, 2
    0x104089f38 <+132>: add x0, x0, #0xe1b ; =0xe1b

    1. 将PC寄存器的低12位清零,得到 0x0000000104089000 (二进制的1位对应16进制的4位,计算机中的内存地址一般用16进制表示,0x开头表示16进制数,所以后16进制数的后三位清零)
      注:PC寄存器中存储的地址是当前要执行的指令地址,低12位清零,代表当前内存页的起始地址
      2、立即数2代表页数,arm64中每一页为4K,即2的12次方。一个数乘以2的12次方,计算机中即是左移12位,即低12位为0。16进制中即低3位为0.
      3、将上述步骤一和步骤二中得到的16进制数相加,得到0x000000010408b000,将0x000000010408b000放入 x0 寄存器
      4、将x0寄存器中的地址值加上0xe1b,得到的结果放入到x0寄存器。

    相关文章

      网友评论

          本文标题:[arm64]4、循环&选择

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