(七)if/else就是goto
2024-10-18 19:58:42
一、CPU如何执行指令
CPU上有数以亿计的晶体管组层的复杂电路,我们先不用管具体电路如何实现;逻辑上我们可以认为CPU由许多寄存器组成,而这些寄存器又由许多锁存器和触发器组成,N个锁存器或触发器就可以构成一个N位寄存器,例如64位CPU是指其寄存器是64位的。
CPU中有以下三种典型的寄存器,这里重点讲一下:
- PC寄存器:用来存放下一条要执行指令的存储地址;
- 指令寄存器:存放当前正在执行的指令;
- 条件寄存器:内部用一个标记位保存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
}
分析:
- if判断被编译为 cmp和jne两条指令,rbp-0x4地址寄存器中的数和0进行比较将比较结果存入条件码寄存器,如果r为0,则将0标志条件码记为1;
- 接着顺序执行jne指令,jne 表示 jump not equal ,此时查看条件码寄存器,如果条件码寄存器值为0则直接将PC寄存器中下一条指令地址置为4a,进而跳转执行4a行指令;
- 末尾51行mov 命令 eax表示一个累加器,0x0实际是一个占位符,整个这条指令相当于为main方法生成了一个默认为0的返回值在累加器里面。
- 假若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
}
分析:
- b行为i赋初始值0,然后顺序执行跳转到1e行;
- 1e行 cmp 指令比较i的值与2
- 22行判断比较结果小鱼等于2则跳转回14行
- 直到jle条件不满足,顺序执行24在累加器中存入默认返回值0.
可见循环操作就是可以将指令执行未知“拨回”已经执行过的行;通过PC寄存器保存下一条要执行的指令、条件码寄存器保存条件运算结果、指令寄存器保存当前执行的指令再加上可以直接修改PC寄存器中下条指令的地址,就可以实现条件分支运算和循环。
最新文章
- 降维PCA技术
- hdu1106 排序水题
- [转]C++中引用(&;)的用法和应用实例
- hdoj 2647 N!Again
- spring+hibernate整合:报错org.hibernate.HibernateException: No Session found for current thread
- android 监听 USB 拔插广播消息
- elasticsearch 索引优化
- poj1456 Supermarket 贪心+并查集
- redis的pub/sub命令
- 2018(2017)美图java服务端笔试(回忆录)
- visio画图有感
- Ceph的BlueStore总体介绍
- java mail session使用Properties的clone方法
- C#中Graphics的画图代码【转】
- C#跳转网页7种方法
- 2018-2019-2 《网络对抗技术》Exp0 Kali安装 Week1 20165202
- ADODB 调用存储过程
- JVM监控启动参数
- oracle_存储过程_有参数_获取部门装置层级树
- tomcat做成服务
热门文章
- Netcore中简单使用MemoryCache
- 基于synchronized锁的深度解析
- W: Possible missing firmware /lib/firmware/i915/bxt_guc_ver8_7.bin for module i915
- 安利下PyAUtoGUI这个库,可自动化控制鼠标键盘
- 解决无法访问 Github
- 3. Hive相关知识点
- Zabbix实现电话告警通知的配置方法分享
- mysql三层体系
- springboot中使用Filter、Interceptor和aop拦截REST服务
- 基于Pycharm的Python开发环境配置