(七)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详解七层过滤> 一.防火墙简介 防火墙其实就是一个加固主机或网络安全的一个设备或者软件而已,通过防火墙可以隔离风险区域与安全区域的连接,同时不会妨碍风险区域的访问.当然需 ...
随机推荐
- 使用netty实现im聊天
简书地址图文更清晰: https://www.jianshu.com/p/f455814f3c40 1.新建maven工程2.引入maven依赖 <dependencies> <de ...
- vue实现带logo的二维码/商品条形码/打印商品吊牌
一.带logo的二维码 1.安装 npm install vue-qr --save 2.在页面或组件中使用 <template> <div id="qrcode" ...
- C++ 基础 5:多态
1 什么是多态 多态按字面的意思就是多种形态.当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态. C++ 多态意味着由继承而产生的相关的不同的类,调用重写函数时,会根据实际的对象类型来执 ...
- 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(1) - 执行在不同CM内核下
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记(1)之执行在不同CM内核下. 文接上篇 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计&g ...
- Java iText+FreeMarker生成PDF(HTML转PDF)
1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等.方便用户查看,下载,打印.目前常用的解决方案是,把相关数据信息,生成对应的pdf文件返回给用户. ...
- 《<SPRING5高级编程(第5版)>_王净译》笔记-【目录】
第一次写这玩意,不知道什么时候能写完,今天项目比较近,期望年底能看完吧. 先定个小目标 20201228 完成 第1章 Spring介绍 第2章 入门 第3章 在Spring中引入IoC和DI 第4章 ...
- 绝对定位元素left、right、top、bottom值与其margin和宽高的关系
绝对定位元素(position: absolute)在其相对定位元素(即文档流中最近的非静态定位祖先元素)中,定位祖先元素的宽度为W,垂直高度为H,则存在以下关系: 元素水平方向 width + le ...
- jdk的动态代理和静态代理你还写不出来嘛???
一.什么叫jdk的代理? 用另外一个对象去代理实际对象的操作 分为动态代理和静态代理二.先说说静态代理 从字面意思来看就是不会改变的,只可以代理某个固定对象的. 静态代理就是通过实现和目标对象实现的同 ...
- ceph单机多mon的实现
ceph默认情况下是以主机名来作为mon的识别的,所以这个情况下用部署工具是无法创建多个mon的,这个地方使用手动的方式可以很方便的创建多个mon 1.创建mon的数据存储目录 mkdir /var/ ...
- Java编码和字符集(详解)
[1]什么是编码? [2]通过生活案例: [3]由权威机构形成的编码表才可以称之为:字符集 ASCII 英文字符集 用一个字节的7位表示 IOS8859-1 西欧字符集 用一个字节的8位表示 GB23 ...