一、CPU如何执行指令

CPU上有数以亿计的晶体管组层的复杂电路,我们先不用管具体电路如何实现;逻辑上我们可以认为CPU由许多寄存器组成,而这些寄存器又由许多锁存器和触发器组成,N个锁存器或触发器就可以构成一个N位寄存器,例如64位CPU是指其寄存器是64位的。

CPU中有以下三种典型的寄存器,这里重点讲一下:

  1. PC寄存器:用来存放下一条要执行指令的存储地址;
  2. 指令寄存器:存放当前正在执行的指令;
  3. 条件寄存器:内部用一个标记位保存CPU算数运算或逻辑运算的结果;

程序执行时CPU不断依据PC寄存器的地址取出一条条指令交给指令寄存器执行,然后PC寄存器中指令地址不断根据指令长度递增,由此可知指令一般是顺序存放的,例外情况是遇到跳转指令会直接替换PC寄存器中的指令地址到指定地址。

二、以if/else看指令执行和跳转

示例代码:

// 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;
}

编译结果:

    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
}

分析:

  1. if判断被编译为 cmpjne两条指令,rbp-0x4地址寄存器中的数和0进行比较将比较结果存入条件码寄存器,如果r为0,则将0标志条件码记为1;
  2. 接着顺序执行jne指令,jne 表示 jump not equal ,此时查看条件码寄存器,如果条件码寄存器值为0则直接将PC寄存器中下一条指令地址置为4a,进而跳转执行4a行指令;
  3. 末尾51行mov 命令 eax表示一个累加器,0x0实际是一个占位符,整个这条指令相当于为main方法生成了一个默认为0的返回值在累加器里面。
  4. 假若r为0,则程序会顺序执行完41后在48跳转到51

三、循环应该怎么干

示例代码:

int main()
{
int a = 0;
for (int i = 0; i < 3; i++)
{
a += i;
}
}

编译结果:

    for (int i = 0; i < 3; i++)
b: c7 45 f8 00 00 00 00 mov DWORD PTR [rbp-0x8],0x0
12: eb 0a jmp 1e <main+0x1e>
{
a += i;
14: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8]
17: 01 45 fc add DWORD PTR [rbp-0x4],eax
for (int i = 0; i < 3; i++)
1a: 83 45 f8 01 add DWORD PTR [rbp-0x8],0x1
1e: 83 7d f8 02 cmp DWORD PTR [rbp-0x8],0x2
22: 7e f0 jle 14 <main+0x14>
24: b8 00 00 00 00 mov eax,0x0
}

分析:

  1. b行为i赋初始值0,然后顺序执行跳转到1e行;
  2. 1e行 cmp 指令比较i的值与2
  3. 22行判断比较结果小鱼等于2则跳转回14行
  4. 直到jle条件不满足,顺序执行24在累加器中存入默认返回值0.

可见循环操作就是可以将指令执行未知“拨回”已经执行过的行;通过PC寄存器保存下一条要执行的指令、条件码寄存器保存条件运算结果、指令寄存器保存当前执行的指令再加上可以直接修改PC寄存器中下条指令的地址,就可以实现条件分支运算和循环。

最新文章

  1. 降维PCA技术
  2. hdu1106 排序水题
  3. [转]C++中引用(&amp;)的用法和应用实例
  4. hdoj 2647 N!Again
  5. spring+hibernate整合:报错org.hibernate.HibernateException: No Session found for current thread
  6. android 监听 USB 拔插广播消息
  7. elasticsearch 索引优化
  8. poj1456 Supermarket 贪心+并查集
  9. redis的pub/sub命令
  10. 2018(2017)美图java服务端笔试(回忆录)
  11. visio画图有感
  12. Ceph的BlueStore总体介绍
  13. java mail session使用Properties的clone方法
  14. C#中Graphics的画图代码【转】
  15. C#跳转网页7种方法
  16. 2018-2019-2 《网络对抗技术》Exp0 Kali安装 Week1 20165202
  17. ADODB 调用存储过程
  18. JVM监控启动参数
  19. oracle_存储过程_有参数_获取部门装置层级树
  20. tomcat做成服务

热门文章

  1. Netcore中简单使用MemoryCache
  2. 基于synchronized锁的深度解析
  3. W: Possible missing firmware /lib/firmware/i915/bxt_guc_ver8_7.bin for module i915
  4. 安利下PyAUtoGUI这个库,可自动化控制鼠标键盘
  5. 解决无法访问 Github
  6. 3. Hive相关知识点
  7. Zabbix实现电话告警通知的配置方法分享
  8. mysql三层体系
  9. springboot中使用Filter、Interceptor和aop拦截REST服务
  10. 基于Pycharm的Python开发环境配置