- 我是一个线程(修订版)
- 我是一个 Java class
- Javascript:一个屌丝的逆袭
- Java : 一个帝国的诞生
- JSP 一个装配工的没落
- TCP/IP 之 大明王朝邮差
- TCP/IP 之大明内阁
- TCP/IP 之蓟辽督师
- CPU 阿甘
- CPU 阿甘之烦恼
- CPU 阿甘:函数调用的秘密
- 我是一个网卡
- 我是一个路由器
- 我是一个进程
- 我是一块硬盘(上)
- 我是一块硬盘(下)
- 我是一个键盘
- 张大胖的 socket
- 张大胖学递归
- 学习面向对象的令狐冲
- 张大胖学数据库
- 数据库村的旺财和小强
- 小李的数据库之旅(上)
- 小李的数据库之旅(下)
- 漫画:什么是机器学习?
- 那些烦人的同步和互斥问题
- IE 为什么把火狐和 Chrome 给打伤了?
- 对浏览器村的第二次采访
- 节约标兵 IE 的自述
- EMail 诞生记
- Email 诞生记(下)
- Http 历险记(上)
- Http 历险记(下)-- Struts 的秘密
- 动物王国的面向对象
- 冯·诺伊曼计算机的诞生
- Http Server : 一个差生的逆袭
- 张大胖的加法器
- 从 1 加到 100:一道简单的数学题挑战下你的大脑
- 编程语言
- Javascript:一个屌丝的逆袭
- 计算机语言之战
- 我和编程语言的爱恨情仇(上)
- 我和编程语言的爱恨情仇(下)
- Android 为什么选择了 Java
- iOS 为什么选择了 Object-C?
- Basic : 一个老兵的自述
- Node.js : 我只需要一个店小二
- 命令式编程 vs 声明式编程
- 编译还是解释?
- 程序人生
- “架构师"小赵
- 师兄说
- 师姐说
- 小王的架构师之路
- 小李的版本管理系统
- 小超穿越记
- 小李的 Build 之路(上)
- 小李的 Build 之路(下)
- 张大胖改 Bug
- 我的编程之路--大学趣事
- 码农小王的一天
- 小李在外企
- 张大胖的需求估算
- 从厨师到码农
- 聊一聊那些神一样的程序员们(上)
- 聊一聊那些神一样的程序员们(中)
- 聊一聊那些神一样的程序员们(下)
- 谁是互联网之父?
- 一个价值百万的创业教训
- 让自己与众不同 - 提升工作的价值
- 看看你的“易燃性”
- 从无聊的工作中寻找价值
- 什么样的学生适合报考计算机?
- 谈谈程序员的职业方向(上)
- 谈谈程序员的职业方向(中)
- 谈谈程序员的职业方向(下)
- 谈谈培训班的作用
- 码农需要知道的“潜规则”
- 学习编程的加速度
- 码农在工作中的必备能力
- 码农和英语
- 老司机经验
- 假如时光能够倒流, 我会这么学习 Java
- 假如我是计算机系老师
- 学会编程, 而不是学会 Java
- 从增删改查中突围
- 抽象:程序员必备的能力
- 懒就一个字
- 编程的自学方法
- 小王买房记
- 从一道面试题谈谈一线码农应该具备的基本素质
- 想写框架的看过来
- 苹果手机变砖头以后
- 如何快速的学习一门技术?
- 唯一不变的是变化: 谈谈微信应用号
- 什么是企业应用?
- 勿以浮沙筑高台
- 为什么敏捷开发难于成功?
- localhost vs 127.0.0.1
- GitHub/Stackoverflow 找工作时有什么用?
- 动词 or 名词 :这是一个问题
- 如何选择入行语言
- 有时候,沉默是金
- 零 Bug 的代码是怎么炼成的?
- 浮点数为什么不精确?
- 文章错误大全
- Open Source--不要为了开源而开源
- 一不留神,代码就腐化了
- 先做个“键盘侠”, 再来写程序
- 不加断点调试的程序员是好程序员
- 码农必备技能:烂代码的处理之道(上)
- 码农必备技能:烂代码的处理之道(下)
- 学习数据结构有用吗?
- 从现在开始,丰富你的简历
- 那些永不过时的书,你看过几本吗?
- 学好编程必备的一个品质你知道吗?
- 你最爱的 Java
- 搞懂了这几点,你就学会了 Web 编程
- Spring 的本质系列(1) -- 依赖注入
- Spring 本质系列(2)-AOP
- 三层架构和 MVC 那点事儿
- Java 帝国之拨云见日识回调
- 小张的 Duck Typing
- JDBC 的诞生
- JDBC 后传
- 一个不安分的 JDBC 驱动
- Java 帝国之 Java bean (上)
- Java 帝国之 Java bean(下)
- Java 帝国之函数式编程
- Java 帝国之函数式编程(下)
- 关于 Java 初学者需要知道的 10 件事
- JUnit 你不知道的那些事儿
- 圣诞礼物:Java EE 的历史
- Java EE 读书指南
- 给小白的 Java EE 指南
- 给小白的 Java EE 指南(2)
- 给小白的 Java EE 生存指南(3) : XML
- 给小白的 Java EE 生存指南(4) : 一只叫 Tom 的猫
- 给小白的 Java EE 指南(5) : AJAX
- 给小白的 Java EE 生存指南(6) :Java 反射
- 闲聊
- "饿了么"初体验
- 来自大脑的控诉
- 一个高中生是怎么玩自媒体的?
- 尝试 分答
- 到底应不应该上培训班?
- 自学编程中遇到问题怎么办?
- 据说 99%的初级程序员看完后都不迷茫了
- 一行代码引发的“血案”
- 对一个死锁问题的思考
- 通过外包进入名企
- 请开往十年前的今天
- 为什么自学中最好有个师傅指导一下?
- 这个网站值得你花时间投入
- 为什么你无法坚持自学编程?
从 1 加到 100:一道简单的数学题挑战下你的大脑
2017 年的第一篇, 写给刚刚踏入计算机编程领域的小白吧。
所谓编程,就是把自然语言的需求翻译成计算机语言, 让计算机去执行。 对于刚入行的人, 理解 CPU 和内存是怎么在一起工作的, 绝对是基础中的基础。
1
CPU 和内存
如果我们简化一下, CPU 和内存其实特别简单,内存就是一个个的小格子, 每个格子都有一个编号, 格子中的数据可以被 CPU 所读写。
CPU 内部的构造超级复杂, 但我们这次只关注两个东西:
一是运算器,可以做各种运算, 但是有个限制,这个 运算器不能直接操作内存进行运算 , 他在运算时使用的是内部的数据格子(学名叫寄存器), 为了区分开, 我把他们叫做 R1,R2,R3,R4,假设只有这么 4 个, 统称 Rx。
CPU 必须把数据装载到寄存器中才能运算。
CPU 运行速度快的令人发指, 但是它能做的事情却简单的令人发指, 主要是以下四种:
(1) 从内存的某个格子中读取数据放入自己内部的寄存器 Rx
(2) 把 Rx 的数据写入内存的某个格子中(会把原有数据覆盖)
(3) 进行数学运算和逻辑运算
(4) 根据条件进行跳转
数学运算就是加减乘除, 逻辑运算就是 AND , OR 这样的基本运算,没接触过的暂时可以不用深究。
根据条件进行跳转就是从一个指令跳转到另外一个指令, 下文会详述。
2
从 1 加到 100
现在我们试图用一个例子来揭开 CPU 和内存的神秘面纱, 这个例子就是把 1, 2, 3, 4,..... 97, 98, 99, 100 这 100 个数字加起来 。
如果你看过数学王子高斯小时候的故事, 自然很简单,不就是 101 * 50 = 5050 吗 ?
作为码农, 我们需要用上面的简化计算机来解决这个问题: 我们需要 精确的 告诉 CPU 来指令, 让它去完成这个加法运算。
切记切记: 内存只是一个个可以读写的格子, CPU 简单到只能做上面描述的 4 件事。
3
热身
在正式开始之前,我们先来热一下身,把你的思维切换一下, 用这个“简陋的”计算机计算一下 50 + 60 , 我门需要告诉 CPU 这些指令:
指令 1 : 把数字 50 放到编号为 #1 的格子里
指令 2 : 把数字 60 放到编号为 #2 的格子里
指令 3 : 把格子#1 的数字取出来,暂时放到 CPU 内部的寄存器 R1 中
指令 4 :把格子#2 的数字取出来, 暂时放到 CPU 内部的寄存器 R2 中
指令 5 :把 R1 和 R2 的值相加, 结果放到 R1 中
指令 6 :把 R1 的结果放到编号为 #1 的内存格子里。
真是不容易啊, 因为 CPU 不能直接操作内存进行加法操作, 需要把数据从内存和 CPU 之间搬来搬去, 最后才完成了这么一个简单的运算。
4
正式出发
热身完毕,正式出发 !
回到那个从 1 加到 100 的题目, 我们的指令如下所示,CPU 需要依次执行(除非遇到跳转指令), 直到结束:
指令 1 : 把数字 0 放到 编号为 #1 的格子里
指令 2 : 把数字 1 放到 编号为 #2 的格子里
指令 3 : 把#1 号格子的数取出放入 CPU 寄存器 R1 (即 R1 的初始值为 0)
指令 4 : 把#2 号格子的数取出放入 CPU 寄存器 R2 (即 R2 的初始值为 1)
指令 5 : 把 R2 的值和 100 比较, 如果小于等于 100,执行第 6 个指令, 否则执行第 9 个指令
指令 6 : 把 R1 和 R2 的数据加起来, 结果放入 R1
指令 7 : 把 R2 的数值加 1
指令 8: 跳转到第 5 个指令
指令 9: 把 R1 的值写回到 编号为 #1 的格子里
(注:#1 号格子的值就是结果)
这里提示一下: R2 表示的就是从 1 到 100 这些数字, R1 存放的就是中间和。
现在,请你在脑子里边模拟一下这个过程, 看看程序能不能成功结束, 把最终结果放到#1 号格子里。
如果觉得脑子不够用, 建议拿一个纸和笔, 把自己当成 CPU, 把上面的这些指令手工的执行一遍, 体会一下这个过程。
如果你是非科班出身,并且能迅速的理解上面这些指令是如何完成从 1 到 100 的加法的, 恭喜你, 你很适合学习编程, 光明的前途在前面向你招手。
我们上面所说的指令和汇编非常相似, 这是一种非常贴近机器, 非常“低级”的计算机语言。
用这种语言来编写大型程序,会把人活活累死。
当然话也不能那么绝对, 对于那些大神级别的程序员来说, 汇编也是小菜一碟。 Ken Thompson 和 Dennis Ritchie 不就用汇编写了第一版的 Unix 操作系统吗? 求伯君不就用汇编写了 WPS 吗?
对于普通人来说,大神们给我们创造了高级语言让我们使用, 如果我们用高级语言把上面的例子再写一遍, 你应该很容易能看明白了:
不要被之前的“低级”指令吓住, 这才是码农每天打交道的代码,不过这种高级语言写的代码最终也要被编译成“低级”语言代码, 最终交由 CPU 来执行, 编译后的机器语言,其实和上面的指令差不多。
5
思考
为什么要拿这个例子来挑战小白的大脑呢? 从本质上来说, 码农整天做的就是这样的事情, 告诉计算机使用这些指令去运算, 我们需要养成面向计算机的思维方式。
CPU 能干的事情非常有限,笼统来说就是上面那四种, 但是我们现在上网、听歌、看视频、玩游戏,最终都会归结到这些操作中来, 这就是计算的本质。
此外, CPU 是如此的冷酷, 以至于你的指令出一点点错误就不给你正确结果, 例如你把第 3 个指令中的“如果小于等于 100”, 不小心写成了“如果小于 100”,
CPU 当然不会告诉你程序中有问题,他只会冷冷的执行, 最后你会发现:这结果怎么不对呢?
还有一个问题,CPU 在运行的时候,从哪里取获得那些指令?
估计你已经想到了, 对,就是内存 ,指令也需要在内存中才能够被 CPU 访问到, CPU 从内存读到指令以后,会进行分析(译码) , 看看这个指令是干什么的, 然后再进行运算。
所以我们的内存小格子中不仅仅存放的是数据,还存放着至关重要的程序指令! 我们需要告诉 CPU 第一条指令在什么地方, 然后 CPU 就可以疯狂的开始运行了:
这些指令在内存中肯定不是我们看到的自然语言, 而是二进制的表示。
那内存的数据又是从哪里来的? 肯定是硬盘了, 我们写好的程序会放在硬盘上, 在运行的时候才调入内存。
最后,再次强烈推荐这本帮你透彻理解计算机软硬件到底是怎么结合工作的书籍:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论