从CPU执行计算机指令层面来看if...else和switch的区别

基础概念:
  • 程序的执行过程:程序(高级语言写的代码)-- 汇编语言 – 到机器语言(CPU可识别的机器代码)
  • 相关汇编语言词汇解释:
    mov:赋值操作,例:mov DWORD PTR [rbp-0x4],0x1;
    jne: (jump if not equal 如果不等于就跳转),例:jne 4a <main+0x4a>
    jmp: (jump)跳转,例:jmp 51 <main+0x51>
    je:(jump if equal 如果等於则跳转),例:je 4a <main+0x4a>
    cmp:(compare 比较),例:DWORD PTR [rbp-0x4],0x0
简单熟悉

我们以c语言代码为例,我们先熟悉一下分析流程:


// test.c


#include <time.h>
#include <stdlib.h>


int main()
{
  srand(time(NULL));
  int r = rand() % 2;
  int a = 10;
  if (r == 0)
  {
    a = 1;
  } else {
    a = 2;
  }
} 

通过一下命令将代码转化为汇编代码,并打印出来:
$ gcc -g -c test.c
$ objdump -d -M intel -S test.o

//其中左边的数字是机器代码,显然不是给人看的。右边是汇编代码,是给程序员看的,我们跟着序号看
    if (r == 0)
  3b:   83 7d fc 00             cmp    DWORD PTR [rbp-0x4],0x0 //1.比较[rbp-ox4]和0x0,如果相等则将零标志条件码设置为1,反之为0
                                                               //DWORD PTR 代表操作的数据类型是 32 位的整数。[rbp-ox4]表示r变量的内存地址
  3f:   75 09                   jne    4a <main+0x4a> //2.判断零标志条件码的结果,如果不是1则跳转到4a(在最左侧,代表行数),加载4a的地址的指令到CPU开始执行
    {
        a = 1;
  41:   c7 45 f8 01 00 00 00    mov    DWORD PTR [rbp-0x8],0x1 //3.如果在第2步没有跳转,那么将执行到这里。把0x1赋值给[rbp-0x8]地址代表的变量a
  48:   eb 07                   jmp    51 <main+0x51> //4.直接跳到51代表的行
    }
    else
    {
        a = 2;
  4a:   c7 45 f8 02 00 00 00    mov    DWORD PTR [rbp-0x8],0x2 //5.把0x2赋值给[rbp-0x8]地址代表的变量a
  51:   b8 00 00 00 00          mov    eax,0x0 //6.结束,继续往下执行
    } 

注:我们回过头去看前面的 if 条件,如果满足的话,在赋值的 mov 指令执行完成之后,有一个 jmp
的无条件跳转指令。跳转的地址就是这一行的地址 51。我们的 main 函数没有设定返回值,而 mov eax, 0x0 其实就是给 main
函数生成了一个默认的为 0 的返回值到累加器里面。if 条件里面的内容执行完成之后也会跳转到这里,和 else
里的内容结束之后的位置是一样的。

分析if…else和switch:

相比到这里,大家应该已经具备汇编语言的阅读能力了,可以尝试自己分析一下!

2段代码如下:
在这里插入图片描述
转化成汇编代码如下:
在这里插入图片描述
由于博主比较懒,大家就自己分析一下吧,希望大家能分析出来为什么我们在写代码的时候,3层判断以内if…else比switch优秀,大于3层的时候,则switch更优。有问题欢迎评论沟通!继续努力!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章