CPU是如何执行指令的?
我们先来简单了解一下CPU。
逻辑上我们简单的理解CPU是由一堆寄存器组成的,代码计算的时候就是执行不同的寄存器。
寄存器里面有触发器和锁存器,简单理解是不同的电路,用来保存数据,但是原理不同。
一般我们说的64位处理器,就是说的寄存器有64位。
都有些啥寄存器?
一个CPU里面有很多不同的寄存器。比较重要的以下三种:
- PC寄存器,也叫指令地址寄存器。用来存放下一条需要执行的计算机指令,主要负责程序的运行顺序。
- 指令寄存器,存放当前执行的指令
- 条件码寄存器,用来存放比较大小,或者逻辑运算得出来的结果,有CF,ZF,SF,OF等条件码,
- 其他寄存器,什么加法寄存器,通用寄存器之类的
一个程序执行的时候,CPU根据PC寄存器里的地址,从内存里把要执行的指令读到指令寄存器里执行,然后指令长短自增,读取一下一条指令。
所以一个程序再内存里是顺序保存的,也会一条条加载。
而J指令,跳转指令会修改PC寄存器里的地址值。这样就不是按内存顺序加载了。也就是我们代码里面的if else while for 等了
if else 是咋实现的?
if (r == 0) {
a = 1;
} else {
a = 2;
}
复制代码
上面是if else 语句,翻译成汇编,是这样的:
if (r == 0)
3b: 83 7d fc 00 cmp DWORD PTR [rbp-0x4],0x0
3f: 75 09 jne 4a <main+0x4a>
{
a = 1;
41: c7 45 f8 01 00 00 00 mov DWORD PTR [rbp-0x8],0x1
48: eb 07 jmp 51 <main+0x51>
}
else
{
a = 2;
4a: c7 45 f8 02 00 00 00 mov DWORD PTR [rbp-0x8],0x2
51: b8 00 00 00 00 mov eax,0x0
}
复制代码
- cmp 指令比较两个操作数的值,DWORD PTR代表数据类型是32位整数,第一个操作数[rbp-0x4]是寄存器里存的内存的地址,这里指的是r的值,第二个操作数0x0就是0。
- cmp比较过后存到条件码寄存器中。
- 如果r == 0为true,就把**零标志条件码(zero flag)**设置为1
- cmp执行完,PC寄存器自增,开始执行jne
- jne先会查看零标志位,如果为0,则跳转到4a这个位置,CPU就把4a地址里的指令加载到指令寄存器来执行。
- 到了4a地址,开始执行mov,[rbp-0x8]是32位整型的寄存器地址,0x2是2的16进制,mov把2设置到[rbp-0x8]寄存器里。是一个赋值操作,这里PC寄存器继续自增执行下一条mov
- 这里的mov 后面的eax代表累加寄存器,0x0是0的16进制,这是一条占位符。主要是用来指示上面如果if符合条件的a=1执行完,就直接跳转到这里。
- 如果没有返回值,编译器会自动添加上return 0,汇编就是mov 0x0,起到占位符的作用
可以看到 if else 就是内存之间的跳转,根据cmp存在条件寄存器不同的值,再通过跳转jne(≠)相不相等jle(≤)小于等于,来跳转到不同的位置去执行代码。
for循环咋实现的?
int main()
{
int a = 0;
for (int i = 0; i < 3; i++)
{
a += i;
}
}
复制代码
对应的汇编
for (int i = 0; i <= 2; i++)
b: c7 45 f8 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0
12: eb 0a jmp 1e
{
a += i;
14: 8b 45 f8 mov eax,DWORD PTR [rbp-0x4]
17: 01 45 fc add DWORD PTR [rbp-0x8],eax
1a: 83 45 f8 01 add DWORD PTR [rbp-0x4],0x1
1e: 83 7d f8 02 cmp DWORD PTR [rbp-0x4],0x2
22: 7e f0 jle 14
24: b8 00 00 00 00 mov eax,0x0
}
复制代码
- mov int类型寄存器设值为0,
- jmp 跳转到 1e地址
- mov 从int类型寄存器添加到累加寄存器
- add 将累加寄存器的值添加到整型寄存器里面
- add 寄存器中添加 1(0x1)
- cmp 比较寄存器中1(0x1),2(0x2),然后存到条件寄存器里面
- jle 根据条件寄存器判断1≤2,跳转到编译之前的14地址,不满足则PC寄存器自增向下执行
- mov 返回一个空
可以看到for循环也是cmp对比了前后的数据,也是一个比较之后的jle(≤)的跳转。
总结
内存上的代码都是按顺序排列好的,执行的时候也是按顺序执行,if else 实际上是PC寄存器的指针跳转,for while 实际上是标记了开始的位置,并写个判断条件,满足条件跳转到开始的位置再顺序执行就实现了我们经常使用的 if else for。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END