1. 预备知识
- inc 指令的功能是将寄存器的内容加一。
- loop 指令的格式是 loop 标号,CPU 执行到 loop 指令时进行两步操作:寄存器 CX 的值减一;判断 CX 中的值,如果为零则向下执行,否则转至标号处执行。使用 loop 实现循环时的三个要点:在 CX 中存放循环次数,loop 指令的标号所标识地址在指令前面,循环体位于标号和 loop 中间。如计算 2 的 11 次方的汇编指令部分:
mov ax,2
mov cx,11 ;循环11次
s: add ax,ax ;寄存器AX的值(2)累加
loop s ;CX的值不为零时转至标号s处
- 在汇编语言中,数据不能以字母开头,即 A002H 要写作 0A002H。
- 在 debug 状态下,指令 g 可以从当前位置快速执行到指定偏移地址处(段地址由寄存器 CS 给出),指令 p 可以一次性执行完所有循环。
- Debug 和 masm 对中括号的处理不同,如 mov ax,[0],前者是将执行内存单元的内容送入寄存器中,而后者是将数值 0 送入寄存器中。在 masm 中正确使用中括号的方式,mov ds:[0] 或 mov ax,[dx] 即显式给出段地址或使用寄存器中转。
- loop 和 [bx] 的联合使用实现循环:用同一方法处理地址连续的内存单元中的数据的问题,需使用循环来解决,同时必须能够在每次循环时按照同一方法来改变要访问内存单元的地址。
- 一般情况下,DOS 和其他合法程序不会使用 0:200~0:300 这段空间。
2. 实验任务
(1)编程,向内存 0:200~0:23F 依次传送数据 0~63(3FH)。
- 题目可翻译为从 0:200 开始写入 64 个值,所以使用 inc 指令来同步内存单元地址及待写值的增长。
- 循环体内完成将值送入指定内存单元,内存单元地址增长和待写值增长。
assume cs:code
code segment ;汇编指令部分开始
mov ax,0
mov ds,ax ;段地址
mov bx,200h ;待写内存单元首地址
mov ax,0 ;待写首值
mov cx,64 ;循环次数
s: mov [bx],ax ;将值送入执行内存单元
inc bx ;内存单元地址增长
inc ax ;待写值增长
loop s
mov ax,4c00h ;程序返回
int 21h
code ends ;汇编指令部分结束
end ;程序结束
- 使用指令 u 查看各指令的位置,然后使用 g 指令直接跳转到指令 int 21h 处,并使用 p 指令完成程序运行。
- 使用指令 d 查看 0:200~0:23f 内存单元的值。
这里,如果我们把 0:200~0:23F 写作 20:00~20:3F(不同地址组合表示相同的物理地址),则偏移地址和待写入值有着相同的增长形式。所以,可以用同一个寄存器同时表示偏移地址和待写入值:
assume cs:code
code segment ;汇编指令部分开始
mov ax,20h
mov ds,ax ;段地址
mov bx,0 ;待写内存单元首地址
mov cx,64 ;循环次数
s: mov [bx],bx ;将值送入执行内存单元
inc bx ;内存单元地址和待写值增长
loop s
mov ax,4c00h ;程序返回
int 21h
code ends 3f ;汇编指令部分结束
end ;程序结束
(2)下面程序的功能是将 mov ax,4c00h 之前的指令复制到内存 0:200 处,补全指令并跟踪运行结果。
assume cs:code
code segment
mov ax,__
mov ds,ax ;设置段寄存器的值
mov ax,0020h
mov es,ax ;设置段寄存器的值
mov bx,0
mov cx,__
s: mov al,[bx]
mov es:[bx],al
inc bx ;偏移地址值加一
loop s
mov ax,4c00h ;程序返回
int 21h
code ends
end
- 在汇编指令中,第 1、2 行设置段寄存器 DS 的值,配合第 7 行确定内存单元;第 3、4 行设置段寄存器 ES 的值,配合第 8 行确定内存单元。
- 由第 7、8 行可知,循环体中每次复制 1 个字节的内容(使用 AL 寄存器中转)。
- 题目要求复制 mov ax,_ 到 loop s 指令到内存 0:200 处,这部分指令长度可以使用 debug 查看(不确定的值随便填):
所以,循环次数为 076A:0000~076A:0016 ,即第 6 行填入的内容为 23 或 17h。
- 循环体部分通过寄存器 AL 中转将 DS:[BX] 的内容移动到 ES:[BX] 内,由 实验2 的内容,CS:IP 存放着指令的地址,所以第 1 行处应使用 CS 寄存器的值给 DS 寄存器赋值。即第 1 行填入的内容为 CS。
完整程序如下:
执行完成后使用 u 指令查看内存单元 0:200 处的内容: