程序的机器级表示
计算机能读懂是机器代码(machine code)—— 用字节序列编码的低级操作 —— 也就是0和1。编译器基于编程语言的规则、目标机器的指令集和操作系统的规则,经过一系列阶段产生机器代码。由于机器语言全是由0和1组成的,所以对于编程人员来说编写机器代码十分困难,也不容易学习。汇编语言(assembly language)就是机器语言的可读形式,学习汇编语言有很多的好处。
An assembly (or assembler) language,[1] often abbreviated asm, is a low-level programming language for a computer, or other programmable device, in which there is a very strong (generally one-to-one) correspondence between the language and the architecture's machine code instructions.
Machine code or machine language is a set of instructions executed directly by a computer's central processing unit (CPU). Each instruction performs a very specific task, such as a load, a jump, or an ALU operation on a unit of data in a CPU register or memory. Every program directly executed by a CPU is made up of a series of such instructions......Numerical machine code (i.e., not assembly code) may be regarded as the lowest-level representation of a compiled or assembled computer program or as a primitive and hardware-dependent programming language.
我们在用高级语言编程时(例如C语言),高级语言本身提供的抽象级别比较高,因此有“程序设计”的概念,方便我们编程。大多数情况下,抽象级别比较高,工作效率就会提高,也更高效可靠。高级语言相较汇编语言的一个最大优点是:用高级语言编写的程序可以在很多不同的机器上运行,而汇编代码与硬件本身有关联,例如指令集不同那么汇编代码就不同。
Each assembly language is specific to a particular computer architecture. In contrast, most high-level programming languages are generally portable across multiple architectures but require interpreting or compiling.
那我们为什么要花时间学习汇编和机器代码呢?
纵观计算机的发展历程,有一个很重要的观点就是用分层的思路来构造整个系统,每个下层都对其上层隐藏本层的细节。这个抽象原理对于理解计算机很多方面的知识都有帮助,例如网络四层模型就是一个很典型的例子。扯回编程语言这块,由于语言是“高级”的,自然屏蔽了很多机器级实现过程的细节。例如,如果只是单纯的学习C语言,那对于寄存器、程序计数器、系统的栈、缓冲区溢出等知识点没有办法很好的理解,因为它们对于C语言程序员来说都是被隐藏的处理器状态。C语言的指针通常是引起错误和不理解的来源,但在汇编中访存、取地址都是很常见的操作。学习汇编,能让你学到一些在C语言学习中由于粒度不够细而学不到的东西。除此之外,读完这一章之后,你还能领略到C语言的伟大之处。
抽象和分层是很重要的思想,但对于严谨的学习者来说,并不意味只要懂得抽象原理就足够了。能够阅读和理解汇编代码是仍是一项很重要的技能。精通细节是理解更深和更基本概念的先决条件。随着时间的推移,对于汇编代码的学习需求也有变化,我们现在不需要直接用汇编语言编写程序,只需要能够阅读并理解编译器产生的代码就可以了。
处理器执行的指令,被编码成二进制形式。一个处理器支持的指令及其编码集称为指令集体系结构(Instruction-Set Architecture, ISA)。
An instruction set, with its instruction set architecture (ISA), is the interface between a computer's software and its hardware, and thereby enables the independent development of these two computing realms; it defines the valid instructions that a machine may execute.
ISA就是机器级程序的格式和行为,这种类型的指令,每一条完成的工作都是非常基本的,例如把两个数相加。因此学习汇编代码就有助于我们了解编译器在把C代码转换成机器代码时所做的转换。相对于C代码,编译器重新排列执行顺序、消除不必要的计算和变量、用基本的、快速的操作代替慢速操作,甚至用迭代替代了递归。学习逆向工程(reverse engineering),来研究高级语言,甚至研究系统创建的过程。(好书啊好书)
可以说,汇编语言很有其特殊性,高级语言的一些抽象的概念,都被归一和具象化了,C语言的指针,在汇编的世界里简直不值一提,因为地址,对地址的引用再平常不过了。另一方面,内存,缓存,寄存器,CPU,又构成了一个奇妙的世界,它们屏息恭立,静待主公的每一条喻令。
我不相信,一个人用纯手工一条条指令去雕琢他的程序,用手指感受计算机的呼吸时会无动于衷。……
作者:匿名用户
链接:https://www.zhihu.com/question/23088538/answer/23631875
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Architecture
汇编内容比较多,部分涉及具体细节的内容有删减,仅做简单介绍,详情请参考书本。
处理器
Intel 处理器系列俗称 x86,经历了一个长期的、不断发展过程。1965年,Intel公司的创始人Gordon Moore,根据当时的芯片技术(那时他们能够在一个芯片上制造大概有64个晶体管的电路)做出推断:未来10年内,芯片上晶体管数量每年都能翻一番。这个预测就是著名的摩尔定律。正如事实所证明的那样,他的预测有点乐观,还有点短视。在超过45年中,半导体工业一直能够让晶体管数量每18个月翻一番。
指令集
就像上面讲到的那样,计算机系统用到了许多不同形式的抽象,利用简单的模型隐藏各种细节。其中之一就是指令集,也就是ISA。在学习汇编时,ISA模型给人的感觉好像看上去应该是顺序指令执行,也就是先取出一条指令,等到它执行完毕,再开始下一条。然而处理器的实际工作方式远比这种模式精细复杂,因为处理器可以并发执行多条指令,因此需要做很多的额外工作。在计算机科学中,用巧妙的方法在提高性能,并完成更多更复杂的功能的同时,又同时保持了一个更简单、更抽象的底层模型功能,这种想法是无处不在的。
IA32和x86-64就是两种ISA,也是着重介绍的重点。这两者是当今大多数计算机的主导语言,后者是前者在64位机器上的扩展版本。
IA32的机器代码和原始C代码差别非常大。下面这些对于C语言程序员隐藏的概念在IA32中是可见的:
-
程序计数器(Program Counter,简称PC)
- 用来指示将要执行的下一条指令的地址。
-
整数寄存器文件(Register File)
- 非常重要的概念。用来存储地址(对应C语言的指针)或者整数数据,或者用来记录程序的状态,或者保持临时数据,例如局部变量、函数的返回值等等。
-
条件码(Condition Code)
- 保持最近执行过的算术or逻辑指令的状态信息。用来实现控制或数据流条件变化。(对应C语言的if等等)
对于机器级编程来说,有第另一种极为重要的抽象,那就是把存储器地址抽象成虚拟地址(Virtual Memory),提供的模型,让机器代码只是简单地把存储器看成是一个非常大的字节数组。所以,C语言中的各种数据类型,和自定义数据类型(struct),在机器代码中都是用一组字节来表示。汇编代码不区分有符号、无符号常数,不区分各种类型的指针,甚至不区分指针和整数。
-
程序存储器(Program Memory)
- 包含程序的可执行机器代码,操作系统需要的一些信息,例如支持系统运行的栈,以及为用户分配的存储器块(例如malloc)。程序存储器用虚拟地址来寻址(Addressable),操作系统负责管理虚拟地址空间,将虚拟地址翻译成实际处理器中的物理地址。
处理器能够执行的操作其实是非常有限的,简单来说只有三种:存取数据、计算和传输控制。存取数据是在内存和寄存器之间传输数据,进行计算则是对寄存器或者内存中的数据执行算术运算,传输控制主要指非条件跳转和条件分支。
代码示例
下面给出一个C语言代码以及其汇编代码中的一些关键行。一开始看不懂没关系,我们只需要对其有一个感性认知。
int accum = 0;
int sum(int x, int y)
{
int t = x + y;
accum += t;
return t;
}
对应的由编译器产生的汇编代码(部分行)如下:
sum:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
addl 8(%ebp), %eax
addl %eax, accum
popl %ebp
ret
观察汇编语言代码,我们可以看到第一个字符串就是操作符,后面可能跟着几个操作数,由逗号分开。操作符就被唯一解码成对应的机器指令,但汇编语言的操作符是能让我们看得懂的。
在汇编代码中,每一行都代表一条机器指令。例如pushl就是把寄存器%ebp的内容压入栈。这段代码已经不存在任何关于局部变量名和数据类型的信息(除了全局变量accum,还没有确定会放在哪里)。
如果使用汇编器(Assembler)将汇编语言翻译为机器语言,机器语言是二进制格式,无法直接查看。但其中有一列17个字节的字节序列:
55 89 e5 8b 45 0c 03 45 08 01 05 00 00 00 00 5d c3
这就是上面列出的汇编指令对应的机器代码。我们可以看出来,机器实际执行的就是对一系列指令进行编码的字节序列。机器对于我们写的C语言代码可以说是一无所知的。
See Also
【CSAPP笔记】4. 汇编语言——基础知识的更多相关文章
-
iOS 阶段学习第11天笔记(OC基础知识)
iOS学习(OC语言)知识点整理 一.OC基础知识 1)#import 用于导入头文件,预处理阶段加载引用,只加载一次. 2)OC 依赖于Foundation框架下的头文件Foundation.h, ...
-
ios开发学习笔记001-C语言基础知识
先来学习一下C语言基础知识,总结如下: 在xcode下编写代码. 1.编写代码 2.编译:cc –c 文件名.c 编译成功会生成一个 .o的目标文件 3.链接:把目标文件.o和系统自带的库合并在一起, ...
-
Spring笔记01(基础知识)
1.基础知识 01.Spring:轻量级Java EE开源框架,它是由Rod Johnson为了解决企业应用程序开发的复杂性而创建. 02.目标:实现一个全方位的整合框架,实现“一站式”的企业应用开发 ...
-
[terry笔记]data guard基础知识
如下介绍了data guard的基础知识,整理自网络: Data Gurad 通过冗余数据来提供数据保护,Data Gurad 通过日志同步机制保证冗余数据和主数据之前的同步,这种同步可以是实时,延时 ...
-
Java 8实战之读书笔记二:基础知识
好记性不如烂笔头,整理一些个人觉得比较重要的东西. 一.基础知识 第1章 为什么要关心Java 8 Java 8提供了一个新的API(称为"流", Stream),它支持许多处理数 ...
-
MySQL必知必会笔记——查询的基础知识
查询基础知识 第七章 数据过滤 组合where子句 MySQL允许给出多个WHERE子句.这些子 句可以两种方式使用:以AND子句的方式或OR子句的方式使用. AND操作符 可使用AND操作符给WHE ...
-
FreeRTOS学习笔记——FreeRTOS 任务基础知识
RTOS 系统的核心就是任务管理,FreeRTOS 也不例外,而且大多数学习RTOS 系统的工程师或者学生主要就是为了使用RTOS 的多任务处理功能,初步上手RTOS 系统首先必须掌握的也是任务的创建 ...
-
《Python基础教程(第二版)》学习笔记 ->; 第一章 基础知识
写笔记的原因:书也看了一遍,视频也看了,但总是感觉效果不好,一段时间忘记了,再看又觉得有心无力,都是PDF的书籍,打开了就没有心情了,上班一天了,回家看这些东西,真的没多大精力了,所以,我觉得还是把p ...
-
[Python笔记]第一篇:基础知识
本篇主要内容有:什么是python.如何安装python.py解释器解释过程.字符集转换知识.传参.流程控制 初识Python 一.什么是Python Python是一种面向对象.解释型计算机程序设计 ...
随机推荐
-
xml &;amp; 符号表示方法,xml转义字符
HTML,xml 中<, >,&等有特别含义,(前两个字符用于链接签,&用于转义),不能直接使用.使用这三个字符时,应使用他们的转义序列,如下所示: & 或 &am ...
-
while;do while;switch;break;continue
1.while: 格式:while(判断条件) { 满足条件要执行的语句 } while语句与for语句对比(小九九) 1.1 for <script>for (var i= ...
-
[Bayesian] “我是bayesian我怕谁”系列 - Naive Bayes+prior
先明确一些潜规则: 机器学习是个collection or set of models,一切实践性强的模型都会被归纳到这个领域,没有严格的定义,’有用‘可能就是唯一的共性. 机器学习大概分为三个领域: ...
-
Visual Studio 使用 Web Deploy 发布远程站点
Ø 简介 本文介绍 Visual Studio 如何使用 Web Deploy发布远程站点,有时候我们开发完某个功能时,需要快速将更改发布至服务器.通常 Visual Studio 可以采用两种方式 ...
-
hadoop集群故障排除
故障一:某个datanode节点无法启动 我是以用户名centos安装和搭建了一个测试用的hadoop集群环境,也配置好了有关的权限,所有者.所属组都配成centos:centos [故障现象] 名称 ...
-
【转】开发者可以使用Docker做什么?
有些开发者可能还是不明白 Docker 对自己到底有多大的用处,因此翻译 Docker 个人用例 这篇文章中来介绍 Docker 在普通开发者开发过程中的用例. Docker 如今赢得了许多关注,很多 ...
-
ADO.NET系列之Command对象
ADO.NET系列之Connection对象 ADO.NET系列之Command对象 ADO.NET系列之DataAdapter对象 ADO.NET系列之事务和调用存储过程 上一篇<ADO.NE ...
-
CentOS6.5之Zabbix3.2.2 Server安装、汉化及Agent安装
1.安装MySQL 1.1.安装MySQL rpm -ivh http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm yum ...
-
关于在webapi + ef + 视图 + top查询的问题
在ef中使用视图中有一种坑是视图没有主键,表现的形式是有些数据会出现重复,解决的方法是手动在视图中添加主键即可 在实际的项目中碰到另一种坑,即使用webapi查询时的一种,现记录情况如下: 1:随便创 ...
-
存储库之mongodb,redis,mysql
一.简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库 MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性 ...