近期利用空闲时间学习了一下汇编,一是为了对计算机底层有多一些了解,希望对自己编码有更好的帮助,
二就是出于好奇和兴趣。目前打算分两篇将自己所学习的笔记和心得整理出来,此篇是第一篇,整理出来自己初学
汇编的一些基本知识点和体会,第二篇整理出简单的汇编的例子,好比学习高级语言的时候,会先写HelloWorld
和一些简单的实现,可以更好的理解所学语言,都是汇编中很基本内容,但初步达到了自己初学汇编的目的,有更
多时间和精力的情况下,就再进行进一步的学习吧。
下面浅谈几点自己的收获和体会:
1. 从CPU的角度考虑问题:我们在应用软件开发的过程中,我们将业务抽象成为类,将业务逻辑封装在对象
里,在开发时我们说是面向对象编程。有一个非常直观的例子:之前做的爬虫的项目,使用Scrapy-redis这个
框架,使用封装好的Spiders , 爬虫就是Spiders , 管理使用这些个Spider , 考虑问题非常接近实际生活中的思维。
在汇编时,我们说,就当是我们在面对CPU编程,需要从CPU的角度来考虑问题,最终运行程序的是CPU,CPU
通过总线与其他器件进行交互,所以先了解一下CPU的主要结构:
运算器:信息处理;
寄存器:信息存储;
控制器:控制各器件进行工作;
内部总线连接各种器件,在它们中间进行数据的传送;
其中寄存器是CPU中的主要部件,所以我们来看一下以x86系列为例的CPU的部分主要寄存器 :
eax : 累加寄存器 功能是运算
ebx : 基址寄存器 存储内存地址
ecx : 计数寄存器 计算循环次数
edx: 数据计数器 存储数据
当然,我们暂时只是列举几个简单的寄存器先作为了解,后面我们再循序渐进的做更多学习。
2. 汇编程序的实际构成:CPU在执行程序时执行机器语言,汇编语言已经非常接近机器语言,不过也需编译
为机器码再执行。翻看计算机的历史,在使用二进制的指令之后,便出于效率和使用难易度等原因,发展出了汇编
语言,至现在发展出我们现在使用的高级语言。我这里将汇编程序的构成分为两部分:
第一部分:汇编指令;
第二部分:伪指令; 其他符号;标号;
第一部分是汇编指令,有对应的机器码,汇编指令是机器码的助记符号。第二部分都由编译器识别和执行,没
对应的机器码。其他符号如+、-、*、/。标号比如在segment前作为段名。伪指令常见的有:
segment 和ends:一个汇编程序由多个段组成。成对出现定义段开始、段结束;
end:整个程序结束标记;
assume:编译时可以将段寄存器和某一个具体的段想联系(ps:类比理解一下java中的import);
proc 和endp : 表示过程的范围。以实现程序“低耦合”“高聚合”;
第二部分针对编译器,第一部分汇编指令则和CPU进行的操作对应,即是对CPU的指令,我们的应用程序解决
了庞大复杂的业务问题,CPU中一个个指令级别的“原子”操作完成了这些复杂的多变的实现。下面看几个简
单的操作码及其应用示例:
mov A, B 把B的值赋给A
and A, B 把A、B的值相加,并将结果赋给A
push A 把A的值存储在栈中
pop A 从栈中读取中值,并将其赋给A
call X 调用函数X
ret 无 将处理返回到函数的调用源
为保障文章篇幅的简洁性,其他更多指令可百度查询其功能。
3. 我们首先了解了汇编语言的构思程序的出发点在CPU,并且简单熟悉了一下汇编的程序组成,那么我们可以
考虑一下对应我们常用的高级语言如java、python,汇编是如何实现高级语言所封装的功能呢。在应用程序的
层面上,我们会使用譬如常见MVC、三层架构或策略模式等等设计模式和架构组成,这些基于高级语言来实现
高级语言的实现又涉及到编译链接、操作系统甚至组成等太多内容,这里我们只关注汇编语言对于高级语言编写
的部分程序的实现,比如函数调用,以及我们学习任何一门语言都会使用的循环(for)实现和条件分支(if)的
实现,这些我们在写程序中重要且很基本的内容,也是计算机作为信息处理工具的本质的部分实现。