产品描述
5SL6613-7CC
一种称为MOV(数据传送)的CPU 指令是图灵完备的。这意味着仅能执行MOV 指令的CPU 与完整的CPU 在功能上并无不同:换言之,通过MOV 指令可以严格地表达任何类型的代码。
这个重要概念在于,无论简单与否,如果程序能采用编程语言进行编码,就可以重写后在任何图灵完备的机器中运行。编译器是一种神奇的程序,能自动将代码从复杂的语言转换为简单的语言。
操作系统
从本质上讲,编译后的计算机程序是CPU 指令的序列。如前所述,为台式计算机编译的代码无法在智能手机中运行,因为二者采用不同的CPU体系结构。不过,由于程序必须与计算机的操作系统通信才能运行,编译后的程序也可能无法在共享相同CPU 架构的两台计算机中使用。
为实现与外界的通信,程序必须进行输入与输出操作,如打开文件、在屏幕上显示消息、打开网络连接等。但不同的计算机采用不同的硬件,因此程序不可能直接支持所有不同类型的屏幕、声卡或网卡。
这就是程序依赖于操作系统执行的原因所在。借助操作系统的帮助,程序可以毫不费力地使用不同的硬件。程序创建特殊的系统调用,请求操作系统执行所需的输入/ 输出操作。编译器负责将输入/ 输出命令转换为合适的系统调用。
然而,不同的操作系统往往使用互不兼容的系统调用。例如,与macOS或Linux 相比,Windows 在屏幕上打印信息所用的系统调用有所不同。
因此,在使用x86 处理器的Windows 中编译的程序,无法在使用x86处理器的Mac 中运行。除针对特定的CPU 体系结构外,编译后的代码还会针对特定的操作系统。
编译优化
优秀的编译器致力于优化它们生成的机器码。如果编译器认为可以通过修改部分代码来提高执行效率,则会处理。在生成二进制输出之前,编译器可能尝试应用数百条优化规则。
因此,应使代码易于阅读以利于进行微优化。编译器较终将完成所有细微的优化。例如,一些人对以下代码颇有微词。
function factorial(n)
if n > 1
return factorial(n - 1) * n
else
return 1
他们认为应该进行以下修改:
function factorial(n)
result ← 1
while n > 1
result ← result * n
n ← n - 1
return result
诚然,在不使用递归的情况下执行factorial 函数将消耗较少的计算资源,但仍然没有理由因此而改变代码。现代编译器将自动重写简单的递归函数,举例如下。
i ← x + y + 1
j ← x + y
为避免进行两次x+y 计算,编译器将上述代码重写为:
t1 ← x + y
i ← t1 + 1
j ← t1
应专注于编写清晰且自解释的代码。如果性能出现问题,可以利用分析工具寻找代码中的瓶颈,并尝试改用更好的方法计算存在问题的代码。此外,避免在不必要的微操作上浪费太多时间。
但在某些情况下,我们希望跳过编译,接下来将对此进行讨论。
脚本语言
某些语言在执行时并未被直接编译为机器码,这些语言称为脚本语言,包括Java、Python 以及Ruby。在脚本语言中,代码由解释器而非CPU 执行,解释器必须安装在运行代码的机器中。
解释器实时转译并执行代码,因此其运行速度通常比编译后的代码慢得多。但另一方面,程序员随时都能立即运行代码而无须等待编译过程。
对于规模较大的项目,编译可能耗时数小时之久。
Google 工程师必须不断编译大量代码,导致程序员“损失”了很多时间(图7-9)。由于需要保证编译后的二进制文件有更好的性能,Google 无法切换到脚本语言。公司为此开发了Go 语言,它的编译速度较快,同时仍然保持很高的性能
反汇编与逆向工程
给定一个已编译的计算机程序,无法在编译之前恢复其源代码。但我们可以对二进制程序解码,将用于编码CPU 指令的数字转换为人类可读的指令序列。这个过程称为反汇编。
接下来,可以查看这些CPU 指令,并尝试分析它们的用途,这就是所谓的逆向工程。某些反汇编程序对这一过程大有裨益,它们能自动检测并注释系统调用与常用函数。借由反汇编工具,对二进制代码的各个环节了如指掌。我相信,许多良好的IT 公司都设有秘密的逆向工程实验室,以便研究竞争对手的软件。
地下经常分析Windows、Photoshop、《侠盗猎车手》等授权程序中的二进制代码,以确定哪部分代码负责验证软件许可证。将二进制代码修改,在其中加入一条指令,直接跳转到验后执行的代码部分。运行修改后的二进制代码时,它在检查许可证前获取注入的JUMP 命令,从而可以在没有付费的情况下运行非法的副本。
在秘密的**情报机构中,同样设有供安全研究人员与工程师研究iOS、Windows、IE 浏览器等流行消费者软件的实验室。他们寻找这些程序中可能存在的安全漏洞,以防御网络攻击或对高价值目标的入侵。在这类攻击中,较**的当属“震网”病毒,它是美国与以色列情报机构研制的一种网络。通过感染控制地下聚变反应堆的计算机,“震网”了伊朗核计划。
开源软件
如前所述,我们可以根据二进制可执行文件分析有关程序的原始指令,但无法恢复用于生成二进制文件的原始源代码。
在没有原始源代码的情况下,即使可以稍许修改二进制文件以便以较小的方式破解,实际上也无法对程序进行任何重大更改(如添加新功能)。一些人推崇协作构建代码的方式,因此将自己的源代码开放供他人修改。“开源”的主要概念就在于此:所有人都能自由使用与的软件。基于Linux 的操作系统(如Ubuntu、Fedora 与Debian)是开源的,而Windows 与macOS 是闭源的。
开源操作系统的一个有趣之处在于,任何人都可以检查源代码以寻找安全漏洞。现已证实,**机构通过日常消费者软件中未修补的安全漏洞,对数百万平民进行利用和监视。
但对开源软件而言,代码受到的关注度更高,因此的第三方与**机构很难植入监控后门程序。使用macOS 或Windows 时,用户必须相信Apple 或Microsoft 对自己的安全不会构成危害,并尽较大努力防止任何严重的安全漏洞。而开源系统置于公众的监督之下,因此安全漏洞被忽视的可能性大为降低。
存储器层次结构
我们知道,计算机的操作可以归结为使CPU 执行简单的指令,这些指令只能对存储在CPU 寄存器中的数据操作。但寄存器的存储空间通常被限制在1000 字节以内,这意味着CPU 寄存器与RAM 之间必须不断进行数据传输。
如果存储器访问速度过慢,CPU 将被迫处于空闲状态,以等待RAM 完成数据传输。CPU 读写存储器中数据所需的时间与计算机性能直接相关。提高存储器速度有助于加快计算机运行,也可以提高CPU 访问数据的速度。CPU 能以近乎实时的速度(一个周期以内)访问存储在寄存器中的数据,但访问RAM 则慢得多。
对于时钟频率为1 GHz 的CPU,一个周期的持续时间约为十亿分之一秒,这是光线从本书进入读者眼中所需的时间。
处理器与存储器之间的鸿沟
近年来的技术发展使得CPU 速度成倍增长。虽然存储器速度同样有所提高,但却慢得多。CPU 与RAM 之间的这种性能差距称为“处理器与存储器之间的鸿沟”。我们可以执行大量CPU 指令,因此它们很“廉价”;而从RAM 获取数据所需的时间较长,因此它们很“昂贵”。随着两者之间的差距逐渐增大,提高存储器访问效率的重要性越发明显
这些数据可以从输入端口上连接的外部器件获得,需要使用传送指令读取这些器件上的数据并送到内部单元;初始数据也可以用程序设置,即向内部单元传送立即数;另外,某些运算数据存储在机内的某个地方,等程序开始运行时通过初始化程序送到工作单元。
(1) 机内数据的存取管理
在数据运算过程中,机内的数据传送是不可缺少的。运算可能要涉及不同的工作单元,数据需在他们之间传送;运算可能会产生一些中间数据,这需要传送到适当的地方暂时存放;有时机内的数据需要备份保存,这要找地方把这些数据存储妥当。总之,对一个涉及数据运算的程序,数据管理是很重要的。
此外,二进制和 BCD 码的转换在数据管理中也是很重要的。
(2) 运算处理向输出端口传送
运算处理总是要通过输出实现对执行器件的控制,或者输出数据用于显示,或者作为其他设备的工作数据。对于输出口连接的离散执行器件,可成组处理后看作是整体的数据单元,按各口的目标状态送入一定的数据,可实现对这些器件的控制。
(3) 比较指令用于建立控制点
控制现场常有将某个物理量的量值或变化区间作为控制点的情况。如温度低于多少度就打开电热器,速度**或低于一个区间就报警等。作为一个控制“阀门”,比较指令常出现在工业控制程序中
产品推荐