4、全局变量 & 循环选择和判断

2021-03-29  本文已影响0人  Jax_YD

首先我们先来简单的回忆一下内存分区:

0x1021ea0f8 <+16>: adrp   x0, 1
0x1021ea0fc <+20>: add    x0, x0, #0xf85            ; =0xf85 

下面我们来解释一下这两条指令:

0x1021ea0f8 <+16>: adrp   x0, 1
这句指令的意思是:
①:将`1`左移`12位`, 得到的结果是:`1000`(注意一个字节是4位)
②:将`pc`寄存器里面的值的后12位清零,然后加上上面的结果,得到的结果是:`0x1021eb000`
此时`x0`的值是`0x1021eb000`

0x1040f60fc <+20>: add    x0, x0, #0xf85
这句指令的意思是:
①:将`x0`与`0xf85`相加
②:将相加的结果再存入`x0`
最终`x0`的值是`0x1021ebf85`

这样就得到了我们的字符串常量Aaron
其实我们的全局变量g也是这样获得的:

WX20210329-105213.png

讲到这里,可能就有人要问了,adrp指令里面的1/7这些又是什么意思呢?其实1就代表4K,怎么来的呢?
首先我们说了:
adrp1要左移12位,就是1000
那么这3个0换成F就是FFF,正好是40950~40954096个数,正好是4K

  • tips:
    MacOS(M1除外)中,内存的一页是4KiOS中一页是16K。这个我们也可以通过终端指令来看一下:

循环选择和判断

首先我们先来认识一个新的指令:cmp(Compare)比较指令



w8 & w9存储的就是我们的a & b,这里就不不做过多的分析。
注意:我们代码中写的是if(a >b)cmp做减法的结果如果是非正数就跳转至:loc_100006100;如果是正数,就接着往下执行。

这就是if else指令的汇编体现。同时我们又认识了一个新的指令:b.le(小于等于)。
再认识一个:b.lt(小于)



可以发现,普通的for循环的汇编指令跟while没有什么区别。

注意 ⚠️ :for in的汇编代码就要复杂很多,有兴趣的同学可以自己编译查看一下。


case 4:
   printf("1");
   break;

我们会发下,当判断条件大于3个的时候,swith的汇编代码就变了,不再是之前的if else。这就是swith底层优化,如果判断条件大于3个的时候,就会创建一个表,表里面存储了每一个case对应的要执行的代码的地址。只要去查表就可以了。(当然,前提条件是,判断条件是连续的有规律的(或者差值不是很大的)。)

下面我们看一下无序的switch:

switch (a) {
        case 0:
            printf("1");
            break;
        case 10:
            printf("1");
            break;
        case 2:
            printf("1");
            break;
        case 40:
            printf("1");
            break;
        default:
            break;
    }

会发现,此时switch又变成了if else

我们在使用switch的时候,要注意case的数量,以及case的规律,这样才能提高代码的质量。

这里我们只是简单的探讨了一下switch,后续我们会针对switch做一下更深入的研究。

上一篇下一篇

猜你喜欢

热点阅读