汇编语言初探

一、什么是汇编语言

汇编语言是(英语:Assembly Language)是一种用于电子计算机、微处理器、微控制器、或其他可编程器件的低级语言。

这是维基百科上对汇编语言的解释。其实汇编语言与常见的 C、C++、Java 等语言一样,都用来 “ 指挥 ” 计算机完成某项工作。只不过汇编语言是直接在硬件上运行的一种编程语言,像 C、C++、Java 等高级语言最终也会被 “ 翻译 ” 成汇编语言。

二、为什么要学习汇编语言

汇编语言是人和计算机沟通最直接的方式,它描述了最终计算机所要执行的指令序列的意义。当你和一个会说八国语言的人交流时,最有效的方式还是和他用母语交流。这个比喻好像有点牵强,但是中心思想就是:通过学习汇编语言我们可以更加深入的理解计算机的工作方式

学习汇编还有一个好处,那就是能体验到底层编程所带来的乐趣。

我目前使用的是 Java 语言进行一些开发,都知道 Java 语言是跨平台的,一个 java 文件(源代码)如下:

public class demo {
    public static void main(String[] args) {
        int a = 1;
        a = 6;
        for (int i = 0; i < a; i++) {
            a++;
        }
    }
}

该文件首先被编译成 class 文件(字节码),再将 class 文件送入 JVM 中执行。JVM 再将 class 文件中的字节码翻译成对应平台的机器码。下面贴出这个 class 文件反汇编后(使用 javap 命令)得到的汇编代码。

虽然这些汇编指令是 JVM 中特有的,但是应用起来和一般微处理器的汇编指令都是相通的。

都说深入 JVM 是一个 Java 高级工程师的必经之路,在我看来知识都是一步一步积累起来的,任何跳跃式的学习都是不靠谱的,让一个连汇编语言都不会的人直接去学习 JVM 相关的知识,效果可想而知。

综合这些因素,我开启了汇编语言的学习之路。在我的学习过程中,主要的参考书籍是王爽教授的 汇编语言 这本书。

三、汇编语言基础知识

(一)机器语言

裸机的概念都知道,指的是没有装配任何操作系统和其他软件的电子计算机。裸机唯一能识别的就是机器语言,就像一个没有接受过教育的人,他还是会用语言表达一件事一样(貌似又是一个糟糕的比喻 – – ! )。

机器语言是机器指令的集合,一台电子计算机的机器指令是一系列二进制序列。计算机将这些二进制转换成相应的高低电平,使计算机的电子器件收到驱动,从而进行一些计算。

(二)汇编语言与 CPU

在计算机中进行计算的功能由 CPU 来完成,每种 CPU 由于硬件设计和内部结构的不同,其机器指令也不相同,每种 CPU 都有属于自己的机器指令集

由于机器指令是一些二进制序列,所以对于程序的编写和修改是十分不方便的。因此就诞生了汇编语言,学习一个新概念一定要知道他的来源,显然汇编语言就是由机器语言直接发展而来,产生的原因就是机器语言二进制形式阅读和书写上的各种不便。

所以学习汇编语言就是在学习机器语言,学习机器语言就是在学习与一个特定 CPU 打交道的方式。只不过汇编语言更加的便于记忆和书写罢了。

  • 操作:寄存器 BX 的内容送到 AX 中
  • 机器指令:1000100111011000
  • 汇编指令:mov ax,bx

既然 CPU 只能识别二进制序列,那么计算机中必然有一个程序能将汇编语言转换成机器语言,这个程序就叫做汇编编译器。针对不同的 CPU,有不同的汇编编译器,那么问题来了,第一个汇编编译器是用什么写的呢?答案应该是机器语言。

汇编语言由下列 3 中指令构成:

  • 汇编指令:机器指令的助记符,与机器指令一一对应
  • 伪指令:没有对应的机器指令,由编译器执行,计算机并不执行(?)
  • 其他符号:没有对应的机器指令,如+、-、*、/等符号

上面说到了 CPU,CPU 是计算机中的核心部件,它是一个强大的计算中心。就拿简单的 1 + 2 这个操作来说,要让 CPU 执行这个操作,首先要让 CPU 知道需要执行的是加法操作(指令),然后需要让 CPU 知道让哪两个数相加(数据)。指令和数据在存储器(存储器的概念在下面说明)中存放。

其实程序和数据在存储器中存放的形式都是一些二进制序列CPU 既能将这些序列看成数据,又能看成指令,就像 1000100111011000,如果 CPU 将其看作数据,这个数的大小就是 89D8H,如果将其看作指令,这个指令就是 mov ax,bx。

(三)存储器

存储器分为:

  • 随机存储器(RAM)
  • 只读存储器(ROM)

其实这两个概念我以前也知道,但也就仅限于概念上的了解。但是在看完汇编语言的第 1 章后,我才知道存储器还有物理意义上的存储器和逻辑意义上的存储器的区别

在介绍各种存储器之前先了解一下主板的概念。

一台计算机中的主板一般长这样:

 

一眼就能看到 CPU 所在的位置和一些黄色的插槽,插槽上可以插各类接口卡(如显卡、网卡、内存卡等)。

具体说来,物理意义上的存储器分为 RAM(读写) 和 ROM(只读)。

其中内存卡全是 RAM,网卡和显卡中有 ROM,ROM 中一般装有 BIOS,它利用对应的硬件进行最基本的输入输出。而显卡中也有 RAM,显卡中的 RAM 就是指的 显存。显卡会随时将显存中的数据向显示器输出。

上面说的是物理意义上的存储器,那什么是逻辑意义上的存储器呢?

逻辑意义上的存储器的概念是针对于 CPU 而言的,CPU 将各种 RAM 和 ROM 看成是一个同一的整体,通过 地址总线 进行寻址,CPU 把这些 RAM 和 ROM 统一的当做内存对待

(四)内存地址空间

在计算机中,所有的物理存储器被看作一个由若干存储单元组成的逻辑存储器。这个逻辑存储器所在的空间被称为内存地址空间

内存地址空间的大小受 CPU 地址总线宽度的限制。 8086CPU 的地址总线宽度为 20,那么它就能寻址 220 个地址单元,即 1MB。所以当你使用 8086CPU 时,即使给它配上 1G 的内存卡,它最多能使用到的内存单元也只有 1MB。

下面是 8086CPU 内存地址空间的分配情况:

 

从地址 0 ~ 9FFFF 的内存单元读取数据,实际就是在读取主随机存储器的数据;向地址 A0000 ~ BFFFF 的内存单元中写数据,就是想显存中写入数据,这些数据会被显示卡输出到显示器上;向 C0000 ~ FFFFF 的内存单元中写入数据是无效的,因为这一段地址空间是只读的。

四、总结

《汇编语言》的第一章主要是介绍了一些计算机硬件基础知识,为下面两张对寄存器的学习做了很好的铺垫。王爽教授的这本书真的挺不错,短短的一章内容就足以让我有了很强的阅读欲望,期待下面两章对寄存器的阅读。

(完)