1
0
mirror of https://github.com/Didnelpsun/CS408.git synced 2026-11-01 04:47:41 +08:00
This commit is contained in:
Didnelpsun
2022-06-24 23:34:36 +08:00
parent f2a4ac07c6
commit 0c5238f35d
2 changed files with 214 additions and 36 deletions

View File

@@ -46,7 +46,7 @@ $C.$编译程序
$D.$解释程序
解:$C$。翻译程序是指把高级语言源程序转换成机器语言程序(目标代码)的软件。翻译程序有两种:一种是编译程序,它将高级语言源程序一次全部翻译成目标程序,每次执行程序时,只需执行目标程序,因此只要源程序不变,就无须重新编译。另一种是解释程序,它将源程序的一条语句翻译成对应的机器目标代码,并立即执行,然后翻译下一条源程序语句并执行,直至所有源程序语句全部被翻译并执行完。所以解释程序的执行过程是翻译一句执行一句,并且不会生成目标程序或机器级目标代码文件。汇编程序也是一种语言翻译程序,它把汇编语言源程序翻译为机器语言程序。汇编语言是一种面向机器的低级语言,是机器语言的符号表示,与机器语言一一对应。
解:$C$。由于是高级语言,所以不可能是汇编,$A$排除。由于是转换为机器代码,所以不是连接,所以$B$排除。编译和解释都属于翻译程序,重点是会转换为目标代码文件,由于解释程序是翻译一条执行一条,所以不会产生代码文件,所以选择$C$。
**例题** 关于相联存储器,下列说法中正确的是()。

View File

@@ -81,18 +81,17 @@
#### I/O设备
输入设备:将程序和数据以机器所能识别和接受的信息形式输入计算机。
输出设备:将计算机处理的结果以人们所能接受的形式或其他系统所要求的信息形式输出
+ 输入设备:将程序和数据以机器所能识别和接受的信息形式输入计算机。
+ 输出设备:将计算机处理的结果以人们所能接受的形式或其他系统所要求的信息形式输出
#### 存储器
用于存放程序和数据。分为主存(主存储器、内存储器)和辅存(辅助存储器、外存储器),$CPU$直接访问主存,只有调入主存才能被$CPU$访问。
用于存放程序和数据。分为主存和辅存,$CPU$直接访问主存,只有调入主存才能被$CPU$访问。
存储器结构:
+ 存储体:存储数据的主体,按地址存取。(相联存储器按内容访存)
+ $MAR$:($Memory\,Address\,Register$)存储地址寄存器,用于访存地址,经过存放地址译码后所选的存储单元。$MAR$位数反映存储单元个数的幂值,与$PC$(程序计数器)长度相等,如$MAR$有$10$位,则有$2^{10}=1024$个存储单元。
+ $MAR$:($Memory\,Address\,Register$)存储地址寄存器,用于访存地址,经过存放地址译码后所选的存储单元。$MAR$位数反映存储单元个数的幂值,与$PC$(程序计数器)长度相等(因为都是指向内存地址),如$MAR$有$10$位,则有$2^{10}=1024$个存储单元。
+ $MDR$:($Memory\,Data\,Register$)存储数据寄存器,用于暂存要从存储器中读或写的信息。$MDR$位数=存储字长,一般为字节的二次幂的整数倍。
+ 时序控制逻辑:产生存储器操作时所需的各种时序信号。
@@ -100,10 +99,14 @@
+ 现代$MAR$和$MDR$被划分进入了$CPU$。
+ 存储单元:每个存储单元存放一串二进制代码。
+ 存储字($word$):存储单元中二进制代码的组合。
+ 存储字($word$):存储单元中二进制代码的组合,即一个存储元存放的数据。
+ 存储字长:存储单元中二进制代码的位数,为$1B$或字节的偶数倍。
+ 存储元:即存储二进制的电子元件,每个存储元可存储$1bit$。
寄存器和高速缓冲寄存器$Cache$都集成在$CPU$上,离$CPU$越近速度越快,所以存取速度上寄存器>$Cache$>内存。
$CPU$包括运算器和控制器,不包括存储器(存储器不同于寄存器)。
#### 运算器
用于算术运算和逻辑运算。
@@ -125,7 +128,7 @@ X|加数|减数|被乘数|除数
+ $CU$:控制单元,分析指令,给出控制信号。
+ $IR$:指令寄存器,存放当前执行的指令,内容来自主存的$MDR$。指令中操作码$OP(IR)$送到$CU$分析指令并发出各种微操作命令序列,地址码$Ad(IR)$送到$MAR$来取操作数。
+ $PC$:程序计数器,存放下一条要指令地址,有自动加$1$以形成下一条指令地址的功能,与主存$MAR$有直接通路。
+ $PC$:程序计数器,存放下一条要指令地址,取指后自动加$1$(一条指令长度,不一定为$1$)以形成下一条指令地址的功能,与主存$MAR$有直接通路。
### 计算机工作过程
@@ -139,6 +142,8 @@ X|加数|减数|被乘数|除数
2. 将指令放入$IR$,并分析指令$OP(IR)\rightarrow CU$。
3. 调用$CU$协同执行指令$Ad(IR)\rightarrow MAR\rightarrow M\rightarrow MDR\rightarrow ACC$。
其中翻译包括:预处理;编译;汇编;链接四个阶段。
如何区分指令和数据:
+ 通过不同的时间段来区分指令和数据,即在取指令阶段(或取指微程序)取出的为指令,在执行指令阶段(或相应微程序)取出的即为数据。
@@ -155,6 +160,8 @@ int main(){
根据计算过程,$a$乘$b$再加上$c$,简单的高级语言背后的转换为机器语言就变成:
指令地址:
主存地址|操作码|地址码|注释
:-----:|:----:|:----:|:--:
0|000001|0000000101|取数a至ACC
@@ -163,12 +170,16 @@ int main(){
3|000010|0000001000|将ab+c,存于主存单元
4|000110|0000000000|停机
数据地址,基本的赋值操作:
主存地址|数据值|注释
:------:|:----:|:--:
5|0000000000000010|原始数据a=2
6|0000000000000011|原始数据b=3
7|0000000000000001|原始数据c=1
8|0000000000000000|原始数据y=0
5|0000000000000010|a=2
6|0000000000000011|b=3
7|0000000000000001|c=1
8|0000000000000000|y=0
分析指令地址对应的五条指令执行流程,基本流程是取指令->获取指令操作码->获取指令地址->根据指令地址取数->放入寄存器->计算:
1. 执行地址为$0$的指令,取指令$1$到$4$,分析指令$5$,执行指令$6$到$8$:
1. $(PC)=0$:程序计数器指向主存地址为$0$的指令。
@@ -198,11 +209,11 @@ int main(){
5. $OP(IR)\rightarrow CU$:将指令寄存器的$000011$操作码传输给控制单元中,控制单元根据操作码知道这是“加法”的指令。
6. $AD(IR)\rightarrow MAR$:控制单元根据取数指令,从存储器中取出指令寄存器的地址为$0000000111$的数,即取出存储地址为$7$的数据$c=1$,将这个地址交给存储地址寄存器负责取出。
7. $M(MAR)\rightarrow MDR$,$(MDR)=000000\,0000000001=1$:存储体根据存储地址寄存器的$0000000111$地址找到地址为$7$的数据$1$,并把$1$放到存储数据寄存器中。
8. $(MDR)\rightarrow X,X=000000\,0000000001=1$:将存储数据寄存器的1放入通用寄存器中。(即加法操作中累加器存放被加数,通用寄存器中存放加数)。
8. $(MDR)\rightarrow X,X=000000\,0000000001=1$:将存储数据寄存器的$1$放入通用寄存器中。(即加法操作中累加器存放被加数,通用寄存器中存放加数)。
9. $(ACC)+(X)\rightarrow ACC$,$(ACC)=7$:控制单元通知算术逻辑单元,将$ab$与$c$相加并存回累加器中。
4. 执行地址为$3$的指令,取指令$1$到$4$,分析指令$5$,执行指令$6$到$8$:
1. $(PC)+=1$,$(PC)=3$:程序计数器完成一条指令自动加一,从而现在指向地址为3的指令。
2. $(PC)\rightarrow MAR$,$(MAR)=3$:存储地址寄存器的值现在置为3,表示它要处理的指令的主存地址为3。
2. $(PC)\rightarrow MAR$,$(MAR)=3$:存储地址寄存器的值现在置为3,表示它要处理的指令的主存地址为$3$。
3. $M(MAR)\rightarrow MDR$,$(MDR)=000010\,0000001000$:根据存储地址寄存器存储的地址$3$,在存储体中找到对应的指令$000010\,0000001000$,并把它放入存储数据寄存器中。
4. $(MDR)\rightarrow IR$,$(IR)=000010\,0000001000$:将存储数据寄存器存储的指令放入指令寄存器中。
5. $OP(IR)\rightarrow CU$:将指令寄存器的000010操作码传输给控制单元中,控制单元根据操作码知道这是“存数”的指令。
@@ -225,16 +236,17 @@ int main(){
4. 虚拟机器(汇编语言机器):不能直接运行汇编语言,必须用汇编程序(汇编器)翻译成机器语言程序,所以是虚拟的。汇编语言与机器语言一一对应。
5. 虚拟机器(高级语言机器):面向用户,必须用编译程序(编译器或解释器)翻译成汇编语言程序。
+ 编译程序:将高级语言编写的源程序全部语句一次全部翻译成机器语言程序,而后再执行机器语言程序(只需翻译一次)。如$C$和$CPP$。
+ 解释程序:将源程序的一条语句翻译成对应于机器语言的语句,并立即执行。紧接着再翻译下一句(每次执行都要翻译)。如$JS$和$Python$。
+ 翻译程序:是指把高级语言源程序转换成机器语言程序(目标代码)的软件。包括编译程序和解释程序。
+ 编译程序:将高级语言编写的源程序全部语句一次全部翻译成目标机器语言程序,而后再执行机器语言程序(只需翻译一次)。如$C$和$CPP$。
+ 解释程序:将源程序的一条语句翻译成对应于机器语言的语句,并立即执行。紧接着再翻译下一句(每次执行都要翻译),所以不会形成目标程序文件。如$JS$和$Python$。
+ 对于$Java$既可以编译也可以解释。
## 计算机性能指标
### 主存储器
+ $MAR$位数反映存储单元的个数(最多支持多少个)。
+ $MDR$位数=存储字长=每个存储单元的大小。
+ $MAR$位数反映内存(而不是外存)单元的个数(最多支持多少个,如果超过了则$MAR$也无法寻址到,等同于没用),反映计算机处理能力和并行能力。
+ $MDR$位数=存储字长=每个存储单元的大小,反映计算机一次性处理的数据大小。
+ 总容量=存储单元个数×存储字长。单位为$bit$。
+ 如$MAR$为$32$位,$MDR$为$8$位,总容量=$2^{32}\times8\div8=3^{32}Byte$,所以为$4GB$。
@@ -258,7 +270,7 @@ int main(){
### 专业术语
+ 系列机。具有基本相同的体系结构,使用相同基本指令系统的多个不同型号的计算机组成的一个产品系列。
+ 系列机。具有基本相同的体系结构,使用相同基本指令系统的多个不同型号的计算机组成的一个产品系列。其特征就是指令系统向后兼容。
+ 兼容。指计算机软件或硬件的通用性,即使用或运行在某个型号的计算机系统中的硬件/软件也能应用于另一个型号的计算机系统时,称这两台计算机在硬件或软件上存在兼容性。
+ 软件可移植性。指把使用在某个系列计算机中的软件直接或进行很少的修改就能运行在另一个系列计算机中的可能性。
+ 固件。将程序固定在$ROM$中组成的部件称为固件。固件是一种具有软件特性的硬件,固件的性能指标介于硬件与软件之间,吸收了软/硬件各自的优点,其执行速度快于软件,灵活性优于硬件,是软/硬件结合的产物。例如,目前操作系统已实现了部分固化(把软件永恒地存储于只读存储器中)。
@@ -389,46 +401,51 @@ DF|Direction Flag|方向标志位|10|若将DF置为1,串操作按减地址方
首先下载[DOSBox](https://www.dosbox.com/download.php?main=1),下载后点击安装。DOSBox即通过软件让在不同的系统如Windows、Linux、MacOS等运行DOS程序,直接操作硬件。
然后下载[MASM5.0](http://www.winwin7.com/soft/27172.html#xiazai),将压缩包解压并把对应文件夹放到指定位置。宏汇编程序MASM是具有宏加工功能的汇编程序。可以用它定义含参数的程序段,在使用的位置上调用它们,汇编时将进行宏指令展开,把宏定义所预先定义的指令目标代码插在该位置上。
然后下载[MASM5.0](http://www.winwin7.com/soft/27172.html#xiazai),将压缩包解压并把对应文件夹放到指定位置。宏汇编程序$MASM$是具有宏加工功能的汇编程序。可以用它定义含参数的程序段,在使用的位置上调用它们,汇编时将进行宏指令展开,把宏定义所预先定义的指令目标代码插在该位置上。
#### 挂载
完成后打开DOSBox的DOSBox.exe程序。
完成后打开$DOSBox$的$DOSBox.exe$程序。
由于这个软件的起始目录是“Z:”,并没有我们电脑上的任何本地目录,所以我们需要首先将我们自己的目录给挂载到DOSBox系统中。
由于这个软件的起始目录是$Z$,并没有我们电脑上的任何本地目录,所以我们需要首先将我们自己的目录给挂载到$DOSBox$系统中。
需要将MASM目录挂载在DOSBox中,输入`MOUNT 挂载虚拟盘符 MASM5.0安装地址`(命令不区分大小写)。如我的MASM5.0安装在D盘的MASM目录下,要挂载到D盘中运行,就要在DOSBox控制台中输入`MOUNT D: D://MASM`。如果挂载成功会显示Drive D is mounted as local directory D://MASM\
需要将$MASM$目录挂载在$DOSBox$中,输入`MOUNT 挂载虚拟盘符 MASM5.0安装地址`(命令不区分大小写)。如我的$MASM5.0$安装在$D$盘的$MASM$目录下,要挂载到$D$盘中运行,就要在$DOSBox$控制台中输入`MOUNT D: D://MASM`。如果挂载成功会显示$Drive\,D\,is\,mounted\,as\,local\,directory\,D://MASM\\$
然后查看部署是否成功,`D:`、`dir`,如果显示列表中出现了DEBUG就代表MASM挂载成功,可以使用里面的DEBUG进行操作。
然后查看部署是否成功,`D:`、`dir`,如果显示列表中出现了$DEBUG$就代表MASM挂载成功,可以使用里面的$DEBUG$进行操作。
然后挂载成功后输入`D:`进入挂载地址,输入`DEBUG`就可以开始使用DEBUG了(汇编程序执行器)。
然后挂载成功后输入`D:`进入挂载地址,输入`DEBUG`就可以开始使用$DEBUG$了(汇编程序执行器)。
此后每次使用DOSBox就必须挂载MASM,非常麻烦,可以在配置文件中配置挂载命令。
此后每次使用$DOSBox$就必须挂载$MASM$,非常麻烦,可以在配置文件中配置挂载命令。
找到DOSBox 0.74-3 Options.bat,双击打开配置文件(注意不要直接修改bat文件),在末尾添加:
找到$DOSBox\,0.74-3,Options.bat$,双击打开配置文件(注意不要直接修改bat文件),在末尾添加:
```bat
MOUNT D: D://MASM
D:
```
就相当于默认挂载,并转到虚拟盘符地址,点击DOSBox.exe可以直接使用DEBUG了。
就相当于默认挂载,并转到虚拟盘符地址,点击$DOSBox.exe$可以直接使用相关工具了。
+ $EDIT$编辑器。
+ $MASM$编译器。
+ $LINK$连接器。
+ $DEBUG$调试器。
#### DEBUG
+ R命令查看、改变CPU寄存器的内容。
+ $R$命令查看、改变$CPU$寄存器的内容。
+ `R`查看所有寄存器内容。
+ `R 寄存器名`查看指定寄存器内容。然后下一行弹出一个:,后面可以添加值,从而能修改指定寄存器内容。
+ D命令查看内存中的内容。其中左边为十六进制值,右边为对应ASCII值。
+ $D$命令查看内存中的内容。其中左边为十六进制值,右边为对应ASCII值。
+ `D 段地址:偏移地址`:查看指定段地址与偏移地址所指向的内存后128个内存单元中内容。
+ `D 段地址:偏移地址 数量`:查看指定段地址与偏移地址所指向的内存后指定数量的内存单元中的内容。
+ E命令改写内存中的内容。
+ $E$命令改写内存中的内容。
+ `E 段地址:偏移地址 数据列表`:从指定段地址与偏移地址所指向的内存开始修改内容为数据列表。数据列表中间以空格分隔。
+ `E 段地址:偏移地址`:不表明数据列表,则控制台会主动给你提供从该地址开始的原数据,可以在后面输入新数据,输入空格后会继续弹出下个地址的原数据,回车结束输入执行修改。
+ `E 段地址:偏移地址 "字符串"`:从指定段地址与偏移地址所指向的内存开始保存字符串值,对应的ASCII码自动转换并保存到内容中。
+ U命令将内存中的机器指令翻译成汇编指令。`U 段地址:偏移地址`。结果分别为地址、机器指令、汇编指令、说明。
+ A命令以汇编指令的格式在内存中写入一条机器指令。`A 段地址:偏移地址`。从该地址开始输入汇编指令保存到对应内存。
+ T命令执行一条机器指令。`T 段地址:偏移地址`。从该地址执行保存的汇编指令。
+ $U$命令将内存中的机器指令翻译成汇编指令。`U 段地址:偏移地址`。结果分别为地址、机器指令、汇编指令、说明。
+ $A$命令以汇编指令的格式在内存中写入一条机器指令。`A 段地址:偏移地址`。从该地址开始输入汇编指令保存到对应内存。
+ $T$命令执行一条机器指令。`T 段地址:偏移地址`。从该地址执行保存的汇编指令。
### 汇编指令
@@ -640,16 +657,177 @@ POP AX
可以将汇编文件使用编译器编译为可执行文件。编写->编译->连接->执行。
如下面就是一个简单的汇编源程序:
```asm
ASSUME CS:codeseg
codeseg SEGMENT
START: MOV AX,0123H
MOV BX,0456H
ADD AX,BX
ADD AX,AX
MOV AX,4C00H
INT 21H
codeseg ENDS
END START
```
#### 定义段
+ $SEGMENT$和$ENDS$是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指令。
+ $SEGMENT$和$ENDS$的功能是定义一个段,$SEGMENT$说明一个段开始,$ENDS$说明一个段结束。
+ $SEGMENT$和$ENDS$的功能是定义一个段,$SEGMENT$说明一个段开始,$ENDS$说明一个段结束。($END$可以视为$END\,SEGMENT$的简写)
+ 一个段必须有一个名称来标识,使用格式为:`段名 SEGMENT`、`段名 ENDS`。
+ 一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当作栈空间来使用。
+ 一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。
+ 段名称最终会被编译、连接程序处理为一个段的段地址。
#### 程序结束
#### 程序框架
$END$是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令$END$,就结束对源程序的编译。
如果程序写完了,要在结尾处加上伪指令$END$。否则,编译器在编译程序时,无法知道程序在何处结束。
$END$除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方。由$START$后面加一个冒号,此后就是汇编指令,即基本的代码段。$END START$即指明入口在$START$位置。
#### 假设
$ASSUME$表示为假设的伪代码,假设某一段寄存器与程序中的某个用$SEGMENT$和$ENDS$定义的段相关联,这样就不用再使用$MOV$指令将段通过通用寄存器移动到段寄存器,从而简化了代码。
如`ASSUME CS:codeseg`将$codeseg$代码段放到$CS$代码段寄存器中。
#### 程序返回
我们的程序最先以汇编指令的形式存在源程序中,经编译、连接后转变为机器码,存储在可执行文件中。
而$DOS$是一个单任务操作系统,所以只能有一个程序运行,所以一个程序结束后,将$CPU$的控制枚交还给使它得以运行的程序,这个过程为程序返回。
返回应该在程序的末尾添加返回的程序段。
如代码的`MOV AX,4C00H`和`INT 21H`。这两句话的意思是$DOS$系统功能调$INT 21H$功能中的一种,表示带返回码结束用户程序。$INT 21H$指令中,寄存器$AX$分为$AH$和$AL$两个部分,$AH$中存入指令码$4C$表示带返回码结束,$AL$为程序返回码。用这个指令返回是不需任何条件,还可顺便关闭打开后忘记关闭的文件,并返回寄存器$AL$的值。
AH|功能|调用参数
:-:|:-:|:------:
00|程序终止(同INT 20H)|CS=程序段前缀。
01|键盘输入并回显|AL=输入字符。
02|显示输出|DL=输出字符。
03|异步通迅输入|AL=输入数据。
04|异步通迅输出|DL=输出数据
#### 错误
+ 语法错误:程序在编译时被编译器发现的错误,容易被发现。
+ 逻辑错误:程序在编译时不能表现出来,在运行时发生的错误,不容易被发现。
#### 编辑
打开DOSBox,挂载后直接运行`EDIT`命令,打开编辑器,编写:
```asm
ASSUME CS:codeseg
codeseg SEGMENT
MOV AX,0123H
MOV BX,0456H
ADD AX,BX
ADD AX,AX
MOV AX,4C00H
INT 21H
codeseg ENDS
END
```
编写完成偶点击File,选择Save然后输入文件名进行保存。然后点击File的Exit退出编辑。
#### 编译
然后运行`MASM`,然后需要输入源程序名。如果源程序文件不是以$asm$为扩展名的话,就要输入它的全名,比如$test.txt$。在输入源程序文件名的时候一定要指明它所在的路径,如`D:\MASM\test.asm`(但是注意此时你已经挂载了$MASM$,所以必须使用`dir`查看当前文件路径,文件路径直接为$test.asm$)。如果文件就在当前路径下,只输入文件名就可以。
然后出现$Object\,filename$,默认是后面括号的内容,如果要修改就输入新名字。
然后是$Source\,listing$,表示列表文件,是编译器将源程序编译为目标文件的过程中产生的中间结果。
最后是$Cross-reference$,表示交叉引用文件,这个文件同列表文件一样,是编译器将源程序编译为目标文件过程中产生的中间结果。
也可以直接加上文件地址输入,如`masm test.asm`。
#### 连接
将生成的$TEST.OBJ$文件连接为可执行的$TEST.exe$文件。
控制台中输入$LINK$进行连接。如果目标文件不是以$obj$为扩展名的话,就要输入它的全名,同理要指明文件路径。也可以直接输入`LINK TEST.OBJ`。
$Run\,file$即表示要生成的可执行文件的名字。$List\,file$映像文件是连接程序将目标文件连接为可执行文件过程中产生的中间结果。$Libraries$即库文件,包含了一些可以调用的子程序,如果我们的程序中调用了某一个库文件中的子程序,就需要在连接的时候,将这个库文件和我们的自标文件连接到一起,生成可执行文件。
此时会提示一个警告:$waning L4021: no stack segment$没有栈段,可以不用理会。得到一个TEST.EXE。
#### 运行
由于是可执行文件,所以可以直接在控制台中输入文件名进行执行。
操作系统是由多个功能模块组成的庞大、复杂的软件系统。任何通用的操作系统﹐都要提供一个称为$shell$外壳)的程序,用户(操作人员)使用这个程序来操作计算机系统工作。
$DOS$中有一个程序$command.com$,这个程序在$DOS$中称为命令解释器,也就是$DOS$系统的$shell$。
所以就是这个运行的$command$将汇编文件的程序加载进入内存,并设置$CPU$的$CS:IP$指向程序的第一条指令,即程序入口,从而使得程序得以运行。程序运行结束后返回$command$中,$CPU$继续运行$command$。
可以使用`DEBUG 程序名`的方式对程序进行监控。使用`R`指令对内存进行查看。可以看到$CX=000F$,即汇编程序一共十五个字节。
### 高级使用
#### [BX]
类似于$[0]$表示内存单元的偏移地址,所以$[BX]$也表示一个内存单元,但是偏移地址在$BX$中。
#### (X)
$(X)$用于表示一个地址或寄存器中的内容。如$(AX)=0010H$,即寄存器$AX$中的内容为$0010H$。如$MOV AX,[2]$等价于$(AX)=((DS)*16+2)$,$ADD AX,2$等价于$(AX)=(AX)+2$。
其中定义$idata$表示常量值的占位,如$MOV AX,[idata]$代表$MOV AX,[$常量$]$。
#### LOOP
为循环指令,格式:`LOOP 标号`。$CPU$执行该指令时会进行两步操作:
1. $(CX)=(CX)-1$。
2. 判断$CX$中的值,里面保存循环次数,不为零则转至标号处执行程序,如果为零打破循环向下执行。
计算$2^{12}$:
```asm
ASSUME CS:CODE
CODE SEGMENT
MOV AX,2
MOV CX,11
S: ADD AX,AX
LOOP S
MOV AX,4C00H
INT 21H
CODE ENDS
END
```
这里的标号$S$就指向的是`ADD AX,AX`指令。循环执行的语句要在标号和$LOOP$指令之间。
在实际编程中,经常会遇到,用同一种方法处理地址连续的内存单元中的数据的问题。
我们需要用循环来解决这类问题,同时我们必须能够在每次循环的时候按照同一种方法来改变要访问的内存单元的地址。这时,我们就不能用常量来给出内存单元的地址(比如$[0]$、$[1]$是常量),而应用变量。`MOV AL,[BX]`中的$BX$就可以看作一个代表内存单元地址的变量,我们可以不写新的指令,仅通过改变bx中的数值,改变指令访问的内存单元。
默认地址的段前缀都是放在$DS$中,可以设置不同的段寄存器从而设置不同的段前缀来简化。
### 多段程序
一个程序不可以只有一个代码段,所以必然存在多个段进行不同的数据操作。
由于$END$和$START$是一组关键字,$END$可以指明程序。
```asm
ASSUME 段寄存器名:段名
段名 SEGMENT
……
定义数据
……
START:
……
数据代码
……
段名 ENDS
END START
```