寒假时,有幸拜读了卡内基-梅隆大学(CMU)的Randal E.Bryant 和 David R.O‘Hallaron的名著——深入理解计算机系统(Computer System: A Programmer‘s Perspective)。这本书是来自CMU的一门叫做“计算机系统导论”的课程。让人遗憾的是,国内的大学貌似喜欢开这么一门课。计算机系统导论是个什么层次的课呢?它涉及到的知识有计算机组成原理,汇编语言,操作系统,编译原理,网络编程等。也就是说,它是一个涉及许多CS基础理论的一门课程,它的目的就是让一个Programmer对于计算机系统有一个宏观的感受与认识,知道自己所学的每一门知识是干什么的,以及它与其他知识的联系。这样,在具体的学习时就有了一个比较清晰的概念了。而不是,学一门知识,听得懵懵懂懂,学得有气无力,学完如释重负,等到需要用到时才恍然大悟,却又痛惜那门课学得时候,瞌睡太多了。
吐槽少说,还是回到主题。假期时,主要学习的章节就是书中第3章——程序的机器级表示,关于汇编语言的部分。所有就此记录整理汇编的知识及一些自己的思考。因为本书所讲的汇编乃是基于IA32(Intel 32bit Archtechture)的汇编,而汇编的格式使用的是AT&T的格式,即寄存器名前加"%"符号,如%esp, 指令名小写,如 mov, 指令的最后一位(汇编代码后缀)表示操作数的大小(b: byte, w: word, l: double word; word表示16位);与此相对应的是Intel和Windows使用的另一种格式,寄存器前不加"%"符号,指令名大写。编程环境为ubuntu 14.04, 编译器为gcc。
平时我们所接触到的语言——工作和学习中使用的,一般都是高级语言,如C++或Java之类。而汇编语言,让多数人讳莫如深,因为它和硬件关系密切,使得不懂计算机原理或体系结构,很难学习汇编。由此也更加让许多人远离了汇编,因为懒得因为要学习汇编就去学习计算机原理。然而汇编是如此重要的一门语言,学习它,不一定要用它,至少你可以更好的理解计算机系统和软件的底层实现。CS领域的一位前辈说过:所有的CS问题,都可以通过增加一个中间层而解决。一个中间层,就是对底层的封装与抽象,并提供友好的接口(Interface)给上一层使用。多数时候我们不需要关系更底层的东西,但是有时候,我们还是不得不到下一层的臭水沟去看看,到底是哪里的问题。
计算机硬件系统由处理器(CPU),主存(Memory),I/O控制器及I/O设备。而处理器又由算数逻辑单元(ALU),控制器,及寄存器文件组成。程序的执行是由处理器控制单元控制I/O设备,如硬盘,将数据加载到主存,再通过对数据的读取,由指令数据控制数据在主存和寄存器间的转移及ALU中的计算。寄存器是一个高速存储文件,可以和处理器进行快速的数据交换,而主存就要慢一些了。在汇编语言中会涉及到的,主要就是对主存和寄存器的操作,因为它们是存储数据的实体。同时,最终的计算还是得有ALU进行。由于存储器的虚拟内存及分页技术,我们所使用到的内存地址都是虚拟地址,而对于汇编语言,存储器被抽象为一个字节数组,每一个字节都有一个地址与之对应,并且可以通过这个这个地址对这一字节存储器中存储的数据进行直接访问。这个虚拟地址,也就是我们在C语言中理解的指针。而虚拟地址到物理地址的转化是存储器的控制器做的事,其实就是一个映射关系。(突然觉得映射是高中数学所学概念中,用得最多的一个之一。记得当时还在想,映射这个鬼东西学了能有什么用。。在哈希表中也会用到它。)
一般把计算机语言的发展划分为几个阶段:最初是针对不同机器的指令集的汇编语言;然后有了对汇编语言进行封装的FORTRAN和C;而在面向对象概念提出后有了C++,C#和Java;而近二十年左右,因为硬件资源的改善而出现了对于程序员友好而对效率不那么友好的各种动态语言,即脚本语言,如Python, Ruby, PHP, Javascript,Perl,Lisp。一层层地往上搭建。我们都知道,计算机中的数据是以二进制编码的,机器是只认识0和1这10种数的。所以,所有的程序代码最终都得翻译成二进制代码。(涉及信息的机器级表示及信息论与编码相关知识。) 最开始的汇编,针对不同的指令集(ISA,Instruction Set Architecture),可以直接由汇编指令通过汇编器翻译成机器代码(二进制代码)。之后的C/C++得先用编译器编译成可执行代码,而在编译器编译的过程中,是先使用编译器将C/C++源码翻译成汇编代码,然后再由汇编器将汇编代码翻译成机器代码。而Java及各种脚本语言则是可以先编译成特定的二进制代码,再通过其解释器(Interpreter),解释运行的。而其解释器,通常是由C/C++编写的。解释器就是一个中间层。如非常著名的Java虚拟机(JVM, Java Virtual Machine)。
深入理解计算机系统讲解汇编语言的方式,就是通过讲解汇编语言的基础语法,并通过将C语言翻译成汇编代码来学习汇编。同时,阅读gcc产生的汇编代码及反汇编器通过目标文件(*.o后缀,UNIX/Linux 系统中的一种中间二进制代码)生成的汇编代码来了解C/C++这样的高级语言是如何实现为汇编代码的,并同时研究其优化。之后内容大致分为:
1>IA32寄存器及其访问;
2>数据传送指令;
3>三种类型操作数与寻址方式;
4>算术和逻辑操作;
5>条件码与控制;
6>过程的程序栈实现;
7>数组的分配与访问;
8>异质的数据结构与指针;
9>gcc编译中,汇编语言与C语言的对应关系总结;
转载请注明地址<http://www.cnblogs.com/qiuyi116/p/4320956.html >,谢谢!