引言
汇编语言是除了机器语言外,最为底层的编程语言。由于机器只能读懂0和1,所以需要转换成人类更易操作的语言(其实设计c等高级语言的原因也包括这点)。
同时呢,汇编语言也是其他很多高级语言通向机器的一个桥梁,比如c语言需要编写好后再编译成汇编语言,再转换为机器语言。
这样的话就可以自然想到,是不是我可以通过一些反编译的手段去破解一些软件或者其他的呢(逆向工程)?
其实也不然,只有机器语言和汇编语言是一一对应的,而高级语言很可能一句话就代表了很多汇编语言的操作,所以正向容易而逆向容易出错。例如一个用c语言编写的程序,不可能被人直接把源代码给破解出来的。这时候就需要用到汇编语言了(黑客最爱)
总之,由于汇编和机器是关联非常密切的,所以学习汇编语言可以让我们更加了解硬件的运作,如何让硬件更有效率的工作。
本博客主要是根据汇编语言与接口技术第四版,以及小甲鱼网课(地址:fishc.com)来写。本人大三计算机专业,第一次学习汇编语言,笔记仅适用于初学者借鉴,如有疏漏望大佬指出。
1.1 汇编语言的产生
机器语言是机器指令的集合;
而汇编语言的主体也是汇编指令。
两种指令区别在于表示方式上,通俗来讲,汇编指令是在机器指令的基础上写成了一种便于我们记忆的格式。定义上来讲,汇编指令叫做机器指令的助记符。
这里举个例子:
比如一个操作的内容是:将寄存器AX的内容移动到寄存器BX中。
用机器语言来写是这样的:1000100111011000
是不是根本看不懂?那么汇编指令呢,就对其进行格式变换,写成了汇编的语言:
MOV BX,AX
mov的意思就是move移动,一般都取三个字母,这样看就很好理解了。值得注意的是,是将后面的移动到前面的,具体操作后面再讲。
寄存器
我们刚才提到了AX BX这些寄存器,这些是什么东西呢?
简单来讲,可以理解为cpu中的内存(注意跟一级二级缓存区分)。一个cpu里面有各种各样的寄存器,比如标志寄存器啊数据寄存器啊等等,每个都有自己的任务。目前只需要知道它们是存储数据啊指令什么的。
而AX和BX这种,暂时理解为寄存器的代号吧(小甲鱼是这么说的)
1.2 汇编语言的组成
汇编语言主要由以下三个部分组成:
-
汇编指令(即机器语言的助记符),也是汇编语言的核心。比如MOV add之类的,后续跟随的操作数也放在一起。
先放一张8086的指令格式图,慢慢理解是可以看懂的。
-
伪指令。
伪指令要区别于汇编指令,汇编指令是可以产生供机器执行的对应机器代码的,而伪指令不会,它主要用于辅助源程序的汇编。比如指定数据存放地址等。这些指令机器无法识别,是通过编译器来识别并执行的。
具体例子可以参考这个https://blog.csdn.net/houyichaochao/article/details/80686076 -
其他符号。
比如加减乘除什么的,也是跟伪指令一样,需要编译器去识别和执行。
1.3 存储器
计算机中的大部分部件都有自己的存储器,我们这里主要学习的是内存。
CPU是负责控制整个计算机的运行和运算,但是我们不能把数据什么的直接放到CPU中(因为实在太多了,cpu又那么贵),所以我们一般会选择硬盘存放。但是CPU又不能直接从硬盘中读取数据,这时候就需要内存这个东西。
内存里面需要存放CPU需要处理的指令和数据。指令的意思是告诉CPU要做什么操作,数据则是告诉CPU要对什么东西操作。
在内存或者硬盘上,数据和指令没有什么区别,都是一些二进制的代码。
比如:
1000100111011000 —> 89D8H (数据)
1000100111011000 —> MOV AX,BX (指令)
具体代表哪一种,是人为说了算的。
1.4 存储单元
存储器会被划分为若干个存储单元,每个存储单元从0开始编号。比如假如一个存储器有128个存储单元,他们的编号就是0~127.
一个存储单元可存放1Byte。1KB的存储器有0~1023共1024个存储单元。
1.5 CPU对内存的读写——总线
前面我们说了,CPU自己不存那么多的数据,而是从内存中获取,主要获取的东西有三类:
- 存储单元的地址(地址信息)
- 器件选择以及读写命令(控制信息)
- 读写的数据(数据信息)
那么究竟这些信息是如何传输的呢?
我们应该都听说过电信号这个东西,如下:
电子计算机能够处理和传输的信号都是电信号,所以要用导线传输。
如果你有过自己装电脑的经历,印象最深刻的一定是插线过程(实在是太麻烦了……)。你所插的那些线,就是总线(Bus)的一部分。
总线在逻辑上分为:
- 地址总线
- 数据总线
- 控制总线
也是分别对应了上面所说的三种信息。
图源自小甲鱼网课
仔细看,地址线中,CPU将自己需要操作的对象的地址发送给内存,告诉内存我现在需要这个地址里的东西。
接着控制线中,CPU发给内存读的信息,告诉它我现在需要进行的操作是读取。
然后内存便知道自己需要做什么了,就将地址号为3的数据交给了CPU。
至于写的指令,和读是一样的,只不过数据是从CPU到内存的。
还记不记得上面提到过,说在内存中指令和数据时无法区分的,两个一样的机器代码既可以代表一种操作,又可以代表一串数据。当时我们只是说可以人为认定它代表什么,而现在我们知道了,从哪条线走的,就是代表哪一类。
如果你见过CPU芯片,肯定就见过黄色的那些针脚(也交管脚),它们是和总线相连的。也可以说这些针脚引出了总线。
一个CPU可以引出的三种总线的宽度分别代表了它在三个方面的性能:
- 地址总线宽度决定了CPU的寻址能力
- 数据总线宽度决定了数据传输一次的数据量
- 控制总线宽度决定了其对其他部件的控制能力
1.5.1 地址总线
通过上面的图我们能知道地址总线是用来传输地址的线,这里我们稍微多讲一点。
你们肯定都知道现在的电脑一般都是64或者32位的,但这个可以理解为双重的概念,即操作系统的位数和CPU的位数。两者是有关联的,简单来说,如果CPU是64位的,操作系统如果低于,就不能完全发挥CPU的性能。
对于CPU的这个参数,它代表的意思是寻址的能力。比如64位的处理器可以寻址2的64次方个地址。理论上来讲每条地址线就有一条导线,所以看起来64位处理器有64条,但实际上不一定是。
更准确一点的说法是,一个CPU有N条地址线,就可以说这个CPU的地址总线宽度为N,可以寻找2的N次方个内存单元。地址总线上能传送多少个不同的信息,CPU就可以对多少个存储单元进行寻址。
1.5.2 数据总线
数据总线同样也有宽度,它决定了数据传输的速度。
就像是公路一样,公路越宽,单位时间走的车就越多(因为速度都差不多一样,好像叫什么震荡频率啊什么的)。
同样也可以用位数来理解。
比如8086处理器,它是16位的数据总线。
如果我们要传输某个数据,它的二进制代码是1101100010001001正好16位,我们就可以一次传输完毕:
如果是8088处理器的话,因为这是一个8位的CPU,所以需要传递两次。注意是从低到高。
这也是位数增加运算速度更快的原因,想想现在的64位CPU
1.5.3 控制总线
控制总线是控制线的总称,控制线主要是CPU对其他器件的控制。
所以有多少跟控制线,就意味着CPU可以对其他器件有多少种控制。
需要知道的是,之前讲的读写命令是由好几根控制线综合发出的,具体的教材上好像不要求掌握,就不多赘述了。
本章结束,注意以上内容均为理论,对实际情况不做讨论。