if…else这样的条件判断语句、while和for这样的循环语句,还有函 数或者过程调用和goto的关系

CPU是如何执行指令的

Intel CPU来说,里面差不多有几百亿个晶体管,我们先不管几百亿的晶体管的背后是怎么通过电路运转起来的,逻辑上,我们可以认为,CPU其实就是由一 堆寄存器组成的。而寄存器就是CPU内部,由多个触发器(Flip-Flop)或者锁存器(Latches)组成的简单路。

N个触发器或者锁存器,就可以组成一个N位(Bit)的寄存器,能够保存N位 的数据。比方说,我们用的64位Intel服务器,寄存器就是64位的。

一个CPU里面会有很多种不同功能的寄存器。我这里给你介绍三种比较特殊的

  • 一个是PC寄存器,我们也叫指令地址寄存器。顾名思义,它就是用来存放下一条需要执行的计算机指令的内存地址。
  • 第二个是指令寄存器,用来存放当前正在执行的指令。
  • 第三个是条件码寄存器,用里面的一个一个标记位(Flag),存放CPU进行算术或者逻 辑计算的结果。

除了这些特殊的寄存器,CPU里面还有更多用来存储数据和内存地址的寄存器。这样的寄存器通常一类里面 不止一个。我们通常根据存放的数据内容来给它们取名字,比如整数寄存器、浮点数寄存器、向量寄存器和 地址寄存器等等。有些寄存器既可以存放数据,又能存放地址,我们就叫它通用寄存器。
在这里插入图片描述

if-else执行过程

下面是一段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; }
  } 

在这里插入图片描述
可以看到,这里对于r == 0的条件判断,被编译成了cmp和jne这两条指令。

cmp指令比较了前后两个操作数的值,这里的DWORD PTR代表操作的数据类型是32位的整数,而[rbp-0x4] 则是一个寄存器的地址。所以,第一个操作数就是从寄存器里拿到的变量r的值。第二个操作数0x0就是我们 设定的常量0的16进制表示。cmp指令的比较结果,会存入到条条件件码码寄寄存存器器当中去。

在这里,如果比较的结果是False,也就是0,就把零标志条件码(对应的条件码是ZF,Zero Flag)设置为 1。除了零标志之外,Intel的CPU下还有进进位位标标志志(CF,Carry Flag)、符符号号标标志志(SF,Sign Flag)以及溢溢出出 标标志志(OF,Overflow Flag),用在不同的判断条件下。

cmp指令执行完成之后,PC寄存器会自动自增,开始执行下一条jne的指令。

跟着的jne指令,是jump if not equal的意思,它会查看对应的零标志位。如果为0,会跳转到后面跟着的操 作数4a的位置。这个4a,对应这里汇编代码的行号,也就是上面设置的else条件里的第一条指令。当跳转发生的时候,PC寄存器就不再是自增变成下一条指令的地址,而是被直接设置成这里的4a这个地址。这个时 候,CPU再把4a地址里的指令加载到指令寄存器中来执行。

跳转到执行地址为4a的指令,实际是一条mov指令,第一个操作数和前面的cmp指令一样,是另一个32位 整型的寄存器地址,以及对应的2的16进制值0x2。mov指令把2设置到对应的寄存器里去,相当于一个赋值 操作。然后,PC寄存器里的值继续自增,执行下一条mov指令。

这条mov指令的第一个操作数eax,代表累加寄存器,第二个操作数0x0则是16进制的0的表示。这条指令其 实没有实际的作用,它的作用是一个占占位位符符。。我们回过头去看前面的if条件,如果满足的话,在赋值的mov 指令执行完成之后,有一个jmp的无条件跳转指令。跳转的地址就是这一行的地址51。因为我们的if…else 之后整个main函数就结束了,所以if指令执行完成之后没有合适的指令可以跳转,于是编译器自动生成了这 样一条废指令,使得if…else条件里的内容结束之后,都能跳转到这同一个位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值