(七)if/else就是goto
一、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寄存器中下条指令的地址,就可以实现条件分支运算和循环。
(七)if/else就是goto的更多相关文章
- Go语言流程控制中的break,continue和goto(七)
break(跳出循环) break用于跳出整个循环,如下: func main() { ;i<;i++{ { break } fmt.Println(i) } } // 0 1 2 3 代码里只 ...
- apue第七章学习总结
apue第七章学习总结 1.main函数 程序是如何执行有关的c程序的? C程序总是从main函数开始执行.main函数的原型是 int main(int argc,char *argv[]); 其中 ...
- Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式
Linux就这个范儿 第15章 七种武器 linux 同步IO: sync.fsync与fdatasync Linux中的内存大页面huge page/large page David Cut ...
- goto语句 switch语句
goto语句 #include <iostream> using namespace std; int main() { int i = 1; number: i++; std::cout ...
- 《学习OpenCV》练习题第四章第七题abc
题外话:一直是打算把这本书的全部课后编程题写完的,中间断了几个月,一直忙于其他事.现在开始补上. 这道题我不清楚我理解的题意是不是正确的,这道题可以练习用OpenCV实现透视变换(可以用于矫正在3维环 ...
- C primer plus 读书笔记第六章和第七章
这两章的标题是C控制语句:循环以及C控制语句:分支和跳转.之所以一起讲,是因为这两章内容都是讲控制语句. 第六章的第一段示例代码 /* summing.c --对用户输入的整数求和 */ #inclu ...
- perl5 第七章 控制结构
第七章 控制结构 by flamephoenix 一.条件判断二.循环: 1.while循环 2.until循环 3.for循环 4.针对列表(数组)每个元素的foreach循环 5. ...
- OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)
OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...
- Iptables详解七层过滤
<Iptables详解七层过滤> 一.防火墙简介 防火墙其实就是一个加固主机或网络安全的一个设备或者软件而已,通过防火墙可以隔离风险区域与安全区域的连接,同时不会妨碍风险区域的访问.当然需 ...
随机推荐
- 关于Java中泛型、反射和注解的扫盲篇
泛型 泛型概念 泛型是在JDK1.5之后引入的,旨在让我们写出更加通用化,更加灵活的代码.通用化的手段在于让数据类型变得参数化,定义泛型时,对应的数据类型是不确定的,泛型方法被调用时,会指定具体类 ...
- 推荐系统,深度论文剖析GBDT+LR
今天我们来剖析一篇经典的论文:Practial Lessons from Predicting Clicks on Ads at Facebook.从这篇paper的名称当中我们可以看得出来,这篇pa ...
- 用DOM和DOM4J写xml文件时,怎样设置xml文档的编码
//在将xml文档传输出去时,利用Transformer中的setOutputProperty方法 TransformerFactory trans = TransformerFactory.newI ...
- 解决IE9弹出json下载提示框
<!-- 开启注解 --> <mvc:annotation-driven> <mvc:message-converters> <bean class=&quo ...
- delphi 设置默认控件得到焦点
如果同一窗体有多个按钮的话,追踪源码发现最后是taborder来的 如: 在空白窗体上拖入两个button (btn1,btn2) 如果在btn2设置default = True 运行后,默认焦点还是 ...
- Javascript 参数传递
又一个基本概念出问题,参数传递都是值传递, var a={x:10} function test(obj){obj=1} test(a) console.log(a) 输出什么,如果你说1,那就错了, ...
- Selective Acknowledgment 选项 浅析 1
抓包的时候,发现 tcp 三次握手中一般会有几个options 一个是mss 一个是ws 一个sack perm 这次主要是来说一说 sack 这个选项: 1. 只重传超时的数据包,比较实用与后 ...
- WPF控件库总结
前言 在使用WPF项目的时候, 一般首要的就是对UI部分的选型, 而WPF相关的UI控件和样式库在Githu也是非常多. 关于UI的部分,可以分为二种: 对控件本身没有很大的需求, 只需要在原有的基础 ...
- Nginx下关于缓存控制字段cache-control的配置说明
HTTP协议的Cache -Control指定请求和响应遵循的缓存机制.在请求消息或响应消息中设置 Cache-Control并不会影响另一个消息处理过程中的缓存处理过程.请求时的缓存指令包括: no ...
- 如何防范CSRF攻击
上一篇文章了解了一下CSRF和XSS的区别,那么这次我们来看看怎么防范CSRF吧 首先,从上篇文章我们可以看得出,CSRF攻击是有着限制的,而我们可以使用这个限制来对他做相关的防范 方法1:后端在接收 ...