汇编语言(王爽)学习

Oyst3r 于 2022-12-29 发布

山再高,往上攀,总能登顶;路再长,走下去,定能到达

人民日报

第一章—基础知识

这一节其实就一句话,机器语言(01)太麻烦了,汇编语言方便记忆和使用

编译器:够将汇编指令转换成机器指令的翻译程序,每一种 CPU 都有自己的汇编指令集

汇编语言由三类指令组成:汇编指令(机器码的助记符,有对应的机器码),伪指令(没有对应的机器码,由编译器执行,计算机并不执行),其他符号(如+,-,*等,由编译器识别,没有对应的机器码)

机器指令:CPU 能直接识别并执行的二进制编码

汇编指令:汇编指令是机器指令的助记符,同机器指令一一对应

指令:指令通常由操作码和地址码(操作数)两部分组成

指令集:每种 CPU 都有自己的汇编指令集

总结:指令和数据是应用上的概念,在内存或磁盘上,指令和数据没有任何区别,都是二进制信息

针对于上图,可能有人会问 CPU 是怎么获取到指令呢?

要想获取单元格中的指令(非专业名词),就要知道指令所在的地址,那么这个地址是由操作系统给到 CPU 中一个名叫程序计数器 PC 的硬件(一种寄存器),简单来说,在 x86 兼容 CPU 上,CS 段寄存器和 IP 寄存器两个寄存器就是实现计算机科学中的 PC 这个概念的具体设施(这个在后面会说到,不要急,现在知道名词即可),主要就是理解操作系统当了一个类似中间商的角色

程序编译后,机器码是存在硬盘(存入硬盘的过程,也是操作系统的功劳,不会波及 CPU),在执行时,机器码被操作系统读入内存


可能大家对存储器这个名词比较陌生,这个可是让 CPU 工作的一个必不可少的东西,要想让一个 CPU 工作,就必须向它提供指令和数据,而指令和数据都在存储器中存放,也就是我们平时所说的内存,在一台 PC 机中内存的作用仅次于 CPU!

存储器划分成若干个存储单元,从 0 开始编号。微机存储器的存储单元可以存一个 Byte,即 8 个二进制位,1 KB = 1024 B,1 MB = 1024 KB,1 GB = 1024 MB,1 TB = 1024 GB

存储器从类型分为随机存储器(RAM)与只读存储器(ROM),随机存储器(RAM)在程序的执行过程中可读可写,必须带电存储,只读存储器(ROM)在程序的执行过程中只读,关机数据不丢失

要想继续学下去不混乱,就把一台 PC 机的各种线先缕清,大体上分为两种,一个相对于 CPU 是外部总线,而另一个是 CPU 内部的线,而两者都可以再细分下去,目前阶段就先了解这么多

CPU 要想进行数据的读写,必须和外部器件(标准的说法是芯片)进行以下 3 类信息的交互

1.地址总线:CPU 通过地址总线来指定存储单元

1 根导线可以传送的稳定状态只有两种,高电平或是低电平。用二进制表示就是 1 或 0
图示有 10 根地址线即一次可以传输 10 位,访问存储单元地址为 1011,寻址范围为 0 ~ (210 - 1)

2.数据总线:CPU 与内存或其他器件之间的数据传送是通过数据总线来进行的

8 根数据线一次可传送一个 8 位二进制数据(即一个字节),传送 2 个字节需要两次;16 根数据线一次可传送 2 个字节(内存对齐核心原理)

3.控制总线:CPU 对外部器件的控制是通过控制总线来进行的,有多少根控制总线,就意味着 CPU 提供了对外部器件的多少种控制,所以,控制总线的宽度决定了 CPU 对外部器件的控制能力

看完以上三点后,咱们就开始举几个具体的例子

CPU 对存储器的读写:

1. CPU 通过地址线将地址信息 3 发出
2. CPU 通过控制线发出内存读命令,选中存储器芯片,并通知它,将要从中读取数据
3. 存储器将 3 号单元中的数据 8 通过数据线送入 CPU,写操作与读操作的步骤相似

CPU 对外设的控制:

CPU 对外设都不能直接控制,如显示器、音箱、打印机等
直接控制这些设备进行工作的是插在扩展插槽上的接口卡。
扩展插槽通过总线和 CPU 相连,所以接口卡也通过总线同 CPU 相连。CPU 可以直接控制这些接口卡,从而实现 CPU 对外设的间接控制。
如:CPU 无法直接控制显示器,但 CPU 可以直接控制显卡,从而实现对显示器的间接控制

最终运行程序的是 CPU,我们用汇编语言编程的时候必须要从 CPU 的角度考虑问题,对 CPU 来讲,系统中的所有存储器中的存储单元都处于一个统一的逻辑存储器中,它的容量受 CPU 寻址能力的限制,这个逻辑存储器即是我们所说的内存地址空间

上面这个图是 8086 中各个存储器地址的分配状况

内存地址空间的大小受 CPU 地址总线宽度的限制,这个就和给电脑换内存时候适配不适配的问题一样,得根据 CPU 的性能和情况去选择合适的内存

再补一张图片吧,可能和这章没啥关系


第二章—寄存器

我们知道一个典型的 CPU 由运算器,控制器,寄存器等器件构成,而且这些器件彼此靠内部总线相连,所以现在我们就清楚了这个所谓的寄存器在一台 PC 机中的位置,然后就顺便聊一下,这些器件的功能吧

运算器:信息处理
寄存器:信息处处
控制器:控制各种器件进行工作
总线:数据传输

(里面有些概念或名词是后面才会涉及到的,现在只要混个脸熟)

8086CPU 有 14 个寄存器:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW 都是 16 位

下面这张图说的是它的结构特性,在 CPU 里面真的是结构决定功能,这句话可能在后面说到段寄存器的时候,读者会更加的认同这句话

然后给大家说一下一个寄存器可以处理的数据尺寸(当然这个在后面栈那一块还会更深入的讨论)

8086CPU 可以一次性处理以下两种尺寸的数据。

(8086 采用小端模式:高地址存放高位字节,低地址存放低位字节)

这一类寄存器通常用来存放一般性的数据,有 AX、BX、CX、DX,它们可分为两个可独立使用的 8 位寄存器

16位	8高位	8低位
AX	AH	AL
BX	BH	BL
CX	CH	CL
DX	DH	DL

注意哈,这个高八位和低八位,就是正好能与上面所说到的高位字节和低位字节所对应的,而 8086 的这种设计(也是为了与之前的 8 位寄存器保持关系),虽然说它是叫 16 位寄存器,但完全可以把它当做两个互不相干的 8 位寄存器(某些情况下,对 AH 或者 AL 这种操作的时候),不会说低 8 位在进数的时候会进到高八位的末尾,这个是不可能的,只会把这个进的数丢弃

其实 mov 可以想成赋值运算,add 可以当作+=,寄存器不区分大小写 ax 和 AX 一样

我们在之前谈 CPU 的外部总线的时候提到,8086CPU 有 20 位地址总线,可以传送 20 位地址,达到 1MB 寻址能力(这个就是个简单的数学题哈,不会算的动动手指),这个时候问题就来了,8086CPU 是 16 位结构,在内部一次性处理、传输、暂时存储的地址为 16 位,那么当我们 CPU 与外部进行交互数据的时候,是不是就会浪费四位啊(别小看 4 位,会让寻址能力从 1MB 下降到 64KB),聪明的人类想出来这种办法,真的厉害–>8086CPU 采用一种在内部用两个 16 位地址合成的方法来形成一个 20 位的物理地址

当 8086CPU 要读写内存时:CPU 中的相关部件提供两个 16 位的地址,一个称为段地址,另一个称为偏移地址
1.地址加法器将两个 16 位地址合成为一个 20 位的物理地址
2.地址加法器采用物理地址 = 段地址 ×16 + 偏移地址的方法用段地址和偏移地址合成物理地址

例如,8086CPU 要访问地址为 123C8H 的内存单元,1230H 左移一位(空出 4 位)加上 00C8H 合成 123C8H

(这个图可能更直观一点)

如果大家对这个为什么 ×16 就代表着移动 4 位,我也找了一张图来说明这个问题

相信你看完这个就可以完全理解辣,也更加感叹人类的智慧哈哈哈哈

持续更新中……