1. 绪论
文章目录
- 1. 绪论
- 1.1 导学
- 1.2 为什么要学汇编语言
- 1.3 由机器语言到汇编语言
- 1.4 计算机的组成
- 1.5 内存的读写与地址空间
- 1.6 汇编语言实践环境搭建
- 参考视频:烟台大学贺利坚老师的网课《汇编语言程序设计系列专题》,或者是B站《汇编语言程序设计 贺利坚主讲》,大家一起看比较热闹。
- 中文教材:《汇编语言-第3版-王爽》(课程使用)、《汇编语言-第4版-王爽》(最新版)。
- 老师的博客:《迂者-贺利坚的专栏-汇编语言》
本篇笔记对应课程第一章(下图倾斜),章节划分和教材对应关系如下。
1.1 导学
课程总共分为7个章节:
- 绪论:简单介绍汇编程序基本概念,并配置汇编环境。
- 访问寄存器和内存:介绍汇编基础机制。
- 汇编语言程序:介绍汇编语言程序的结构。
- 内存寻址方式:编写程序时需要频繁的与访问内存,介绍汇编语言提供的非常多的寻址方式。
- 流程转移与子程序:程序执行过程中会有流程上的转移,也就是程序的模块化设计。
- 中断及其应用:在解决实际问题时,汇编程序需要频繁用到中断,包括内中断、外中断。
- 高级汇编语言技术:补充教材中没有的“宏汇编”相关知识。
学习过程中建议先看教材对应章节,再看视频,最后完成教材中的检测点、实验。
1.2 为什么要学汇编语言
只有机器语言可以直接在计算机上运行,而 “汇编语言(Assembly Language)”就是使用简单的助记符来表示“机器语言”。所有的高级语言都是在“汇编语言”之后产生的,是所有程序设计语言的鼻祖(如上图)。虽然汇编语言是一门古老的语言,但是其在某些领域是不可替代的,所以即使在2024年,汇编语言在“TIOBE排行榜”仍然位列第12、“TIOBE指数”整体也是上升趋势,并且随着嵌入式、物联网的普及而经常使用。汇编语言之所以仍在发挥不可替代的作用,主要是因为以下两点:
- 效率:汇编语言常用于开发软件的核心部件,可以被快速执行和实时响应,运行效率高。进行底层驱动开发时,汇编语言的开发效率很高,但开发高级功能的效率非常低。
- 底层:最底层的程序设计只能使用汇编语言,如计算机及外围设备的驱动程序、操作系统的内核、物联网设备等。
而我们通过学习汇编语言,则可以直击计算机系统的核心。不仅可以感知、体会和理解机器的逻辑功能,学会底层的程序调试和错误分析方法,还能够加深对计算机原理和操作系统等课程的理解。简单来说,学习汇编语言 向上为理解各种软件系统的原理,打下技术理论基础;向下为掌握硬件系统的原理,打下实践应用基础。
本课程《汇编语言程序设计》目的在于,理解硬件结构,掌握指令集,理解程序的运行过程。内容上以较为古老的 8088、8086 指令集 为模板,介绍汇编语言程序设计。不直接学习现代处理器(如80x86),是因为现在的计算机系统非常复杂,直接学习会非常混乱,不利于掌握基础知识,本课程结束后,还有兴趣的同学可以继续延伸学习 Intel 80x86汇编、Linux 汇编、ARM 汇编 等。
本课程采用 贯穿实践的方法 讲解知识,并会详细介绍对debug工具的使用帮助同学们观察机器的内部状态。希望同学们结合教材和视频学习知识点后,一定要完成教材上对应的“检测点”、“实验”(如下图)。另外,老师也会设计一些实践性的内容,公布到老师的博客里。实践出真知!
1.3 由机器语言到汇编语言
“机器指令”是一台机器可以正确执行的命令,由一串二进制数表示(比如01010000),一条或几条“机器指令”就构成一条“机器语言”。早期程序员们需要将 0/1 数字编程的程序代码直接打在纸带或卡片上,再通过纸带机或卡片机输入计算机,来完成程序的运行。显然,这样的机器语言程序很难debug。为了解决“机器指令”难以记忆和debug的问题,人们很容易就想到使用一些特定意义的单次表示特定的指令,于是就诞生的“汇编指令”。“汇编指令”是机器指令便于记忆的书写格式,汇编指令是机器指令的助记符。如下:
【例】使用 8086CPU 完成运算 S = 768 + 12288 - 1280,机器码如下:
101100000000000000000011 000001010000000000110000 001011010000000000000101
【例】对于操作——“将寄存器BX的内容送到AX中”,比较机器指令和汇编指令。
机器指令:1000100111011000
汇编指令:MOV AX, BX
汇编语言是直接针对机器进行编程的,比如上面的例子中就是对于寄存器的移动。计算机的各个主要部件都有自己的寄存器,下图给出了计算机的物理实物,在编写汇编程序时我们 无需关心这些器件的电气特性,只需要知晓“逻辑结构”即可,比如CPU寄存器、总线结构等(如上图)。后面我们还会详细介绍各个部件内部的寄存器。用汇编语言编写程序的工作过程如下:
- 编写程序:汇编程序包括汇编指令、伪指令、其他符号,如下图。其中,“伪指令”并不是由计算机直接执行的指令,而是帮助编译器完成“编译”的符号。
- 编译:将汇编程序转换成机器码。
- 计算机执行。
1.4 计算机的组成
计算机组成
首先将这个计算机由表到内的简单介绍一下计算机组成。上图给出了计算机主板的示意图。主板上几个非常重要的部件:
- CPU:中央处理器。
- 总线:运行过程中传输数据、指令,也就是主板上的PCB排线和接口。
- 内存(条):工作过程中保存数据。
- 扩展槽:主要用于链连接外部设备,如打印机、显示器等。
上一小节提到,我们只需关心计算机的逻辑结构即可,实际上我们只关心 “CPU”如何和“内存储器”进行交互。因为没有内存,再强大的CPU也无法工作,所以我们要了解这个交互过程。下左图给出的CPU内部结构后续章节会详细介绍;下右图则主要给出了各主要部件的存储结构:
- 【CPU】CPU 是计算机的核心部件,它控制整个计算机的运作并进行运算。要想让一个CPU工作,就必须向它提供指令和数据。
- 【RAM】随机存储器,能读能写,掉电易失,存储计算机运行过程中动态变化的数据。上图中包括“RAM(主存储器)”(直接焊在主板上)、“RAM(主存储器)”(内存条)、“RAM(显存)”(显卡)。
- 【ROM】只读存储器,只能读不能写,存储无需改变的数据,如计算机启动时需要用到的数据。上图中包括“ROM(装有系统BIOS)”(直接焊在主板上)、“RAM(装有显卡BIOS)”(显卡)、“ROM(装有网卡BIOS)”(网卡)。
指令和数据的表示
计算机中的数据和指令,都是以二进制的形式存储在内存或磁盘上。平常用不到的信息或较大的文件都是存储在“机械硬盘”、“固态硬盘”中,而计算机运行的中间数据则是存储在“内存条”中。那对于如何区分数据和指令呢?主要是看CPU如何使用,比如对于相同的二进制数,其作为“数据”、“指令”的含义是不一样的。下面给出一个例子,并介绍不同进制的表示:
- 数据:
1000100111011000
─>89D8H
- 指令:
1000100111011000
─>MOV AX,BX
数据表示:使用后缀区分进制,单位常用“字节(Byte)”——B、KB、MB、GB、TB等。
二进制:1000100111011000B。
八进制:104730O,汇编语言几乎不用。
十进制:35288D,有时不写后缀默认十进制。
十六进制:89D8H,汇编语言中使用最多。
计算机中的存储单元
那数据或者指令是如何保存在内存之中呢?很简单,存储器被划分为若干个存储单元,每个存储单元从0开始顺序编号。如下图所示,该存储器有128个存储单元,编号从0~127,如下左图所示。但实际上内存空间很“大”,比如8086有20根地址线,寻址空间为 220= 1MB,使用十六进制表示,如下右图所示:
计算机中的总线
上段中提到了“地址线”的概念,其是“总线”的一种。“总线(Bus)”就是在计算机中专门连接CPU和其他芯片的导线,物理上是多根导线的集合,在逻辑上主要分为以下三种:
- 地址总线:CPU是通过地址总线来指定存储单元的。地址总线宽度,决定了可寻址的存储单元大小,比如位宽为 N 的地址总线对应的可寻址空间为 2N。
- 数据总线:CPU与内存或其它器件之间的数据传送是通过数据总线来进行的。数据总线的宽度决定了CPU和外界的数据传送速度,也就是一次性能传输多少数据。例:向内存中写入数据89D8H时的数据传送。
- 控制总线:CPU通过控制总线对外部器件进行控制。控制总线是一些不同控制线的集合,控制总线宽度决定了CPU对外部器件的控制能力。
显然,数据总线宽度越大,单次传输的数据越多,相同的时钟周期也就能传输更多数据,CPU性能越高,如下表:
CPU | 地址总线宽度 | 寻址能力 | 数据总线宽度 | 一次传送数据 | 读取1KB数据所需次数 |
---|---|---|---|---|---|
8080 | 16 | 640KB | 8 | 1B | 1024 |
8088 | 20 | 1MB | 8 | 1B | 1024 |
8086 | 20 | 1MB | 16 | 2B | 512 |
80286 | 24 | 16MB | 16 | 2B | 512 |
80386 | 32 | 4GB | 32 | 4B | 256 |
1.5 内存的读写与地址空间
CPU对存储器的读写
汇编语言是直接和内存打交道的,所以了解内存的读写过程和地址空间非常重要。CPU要想进行数据的读写,必须和外部器件进行三类信息的交互——地址信息(存储单元的地址)、控制信息(器件的选择、读或写命令)、数据信息(读或写的数据)。比如下面给出汇编指令 MOV AL,[3]
的操作过程,其含义是从3号单元读取数据送入寄存器 AL,读写过程如下:
- 发送地址:CPU通过地址线将“地址信息”发送给内存。
- 发送命令:CPU通过“控制线”发出读命令。
- 读取数据:内存接收到地址信息和读命令之后,将相应单元的数据通过“数据线”发送给CPU。
内存地址空间
那内存是如何根据地址找到数据的呢?就需要涉及到“内存地址空间”的概念,也就是在“1.4节-计算机的组成”中提到的“存储单元划分”。从CPU角度来说,可以将各类存储器看作一个逻辑存储器,也就是 统一编址,优势是无需区分各个设备,便于统一管理。比如 8086CPU 的地址总线宽度为20,那么可以寻址1MB个内存单元,其内存地址空间为1MB。
于是按照“1.4节-计算机的组成”中提到的“计算机主板的逻辑组成”,我们就可以将所有的物理存储器被看作一个由若干存储单元组成的逻辑存储器;看成一个整体。每个物理存储器在这个逻辑存储器中占有一个“地址段”,即一段地址空间;CPU在这段地址空间中读写数据,实际上就是在相对应的物理存储器中读写数据。如下图所示:
- 主存储器地址空间:占用空间较大,包括主板上直接焊接的RAM、内存条。
- 显存地址空间:主要是显卡的RAM。
- 各类ROM地址空间:ROM通常相对较小,所以可以直接放在一起。
1.6 汇编语言实践环境搭建
再次强调一下,本课程选择 8086 作为教学模型。这是因为 8086 虽然“高龄”,但其引脚数量、指令系统、寻址方式等都比较丰富,且又不像 Intel Pentium 系列处理器那么复杂。学习 8086 便于初学者快速掌握理解计算机底层工作原理,并且也可以作为未来继续学习 80x86汇编、Linux汇编、ARM汇编 的基础。
本课程会搭配一系列实践教程进行学习,DOS系统(桌面操作系统)很经典,要配置 DOS环境 主要有以下三种方式:
- 物理机:由于系统太古老了,现在很难找到能实际运行的物理机。
- 虚拟机:DOS虚拟机配置环境太麻烦,很可能消减学习欲望。
- 模拟程序:直接使用免费的“DOS模拟器”,可以安装在任意常见的操作系统上,其官网如下图所示。
- 官网下载安装包:如下图,后续要注册。
- 老师提供安装包:“8086汇编语言工作环境”,或者直接看我的百度网盘“8086汇编工作环境.zip(1.76MB)”。
最后介绍 DOS Box 的安装步骤:
安装步骤:教学视频-6汇编语言环境搭建—4:40~最后
拷贝命令文件:将整个 MASM 拷贝到已知路径(建议路径尽量简单),作为工作目录。内容介绍如下图。
安装DOSBox:直接运行安装文件。
启动DOSBox并挂接工作目录:安装完成后会在桌面看到DOSBox图标,双击即可运行。可以发现 DOSBox 的当前目录默认在Z盘,需要将刚才的 MASM 文件夹作为DOS系统的C盘挂载上来,然后将DOS系统的C盘作为工作目录,如下命令。注意这个C盘不是本机的C盘,而是对应的MASM文件夹。
mount c d:\masm c: dir