【CSAPP笔记】4. 汇编语言——基础知识
程序的机器级表示
计算机能读懂是机器代码(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是一种面向对象.解释型计算机程序设计 ...
随机推荐
- NoSQL入门第二天——Redis入门介绍
一.基本概述 1.是什么 Redis:REmote DIctionary Server (远程字典服务器) 是完全开源免费的,用C语言编写的,遵守BSD协议, 是一个高性能的(key/value)分布 ...
- Java基础——类加载机制
什么叫类加载 JVM把 .class 字节码文件加载到内存,并进行相关的校验.解析.初始化,最终转换为虚拟机可用的JAVA类型的过程,称为JVM类加载机制. (当然,JVM并不关心class文件的来源 ...
- 17-[JavaScript]- 内置对象 Array,String,Date,Math
1.Array数组 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...
- CF 1117 E. Decypher the String
E. Decypher the String 链接 题意: 有一个字符串,一些操作,每次操作交换两个位置的字符,经过这些操作后,会得到新的字符串.给你新的字符串,求原来的串.可以有3次询问,每次询问给 ...
- 自动色彩均衡(ACE)快速算法
ACE算法源自retinex算法,可以调整图像的对比度,实现人眼色彩恒常性和亮度恒常性,通过差分来计算目标点与周围像素点的相对明暗关系来校正最终像素值,有很好的增强效果.但是计算复杂度非常高,本文提出 ...
- 新买的orico蓝牙usb连接器使用方法与驱动
因为买的型号是 BTA-403 ,所以需要下载该型号驱动 安装好后,可能会出现找不到蓝牙设备问题,所以需要重启机器,并且手动将pc蓝牙连接到手机蓝牙,然后手机蓝牙再连接蓝牙耳机,此时蓝牙耳机会显示连接 ...
- setjmp/longjmp 处理异常
#include <stdio.h> #include <stdlib.h> #include <setjmp.h> jmp_buf jb; void f1() { ...
- 通俗地讲Node.js是什么
前后端分离,使得后台只需关注服务即可,但有时候开发的不同步,前台往往需要等待后台的接口,通俗的说,“node.js就是一个前端觉得写个功能还要等后端捣鼓半天,然后干脆就自己用javascript把后端 ...
- selenium 基本常用操作
from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains #鼠标操作 ...
- Flink架构分析之资源分配
Task Slot Flink中每个真正执行任务的TaskManager都是一个JVM进程,其在多线程环境中执行一个或者多个子任务.为了控制一个JVM同时能运行的任务数量,flink引入了ta ...