实验四
题目预览
- 编程,向内存0:200~0:23F依次传送数据0~63(3FH)
- 编程,向内存0:200~0:23F依次传送数据0~63(3FH),程序中只能使用9条指令,9条指令中包括“mov ax,4c00h”和"int 21h"。
- 下面的程序的功能是将“mov ax,4c00h”之前的指令复制到内存0~0:200处,补全程序。上机调试,跟踪运行结果。
1&2
因为第一题和第二题差不多就放一起写了。
1&2 编程,向内存0:200~0:23F依次传送数据0~63(3FH),程序中只能使用9条指令,9条指令中包括“mov ax,4c00h”和"int 21h"。
我们分析一下。
(1)0:200~0:23F单元等同于0020:0~0020:3F单元,它们描述的是同一段内存空间。
(2)0:200~0:23F可以表述为0~3F,即0~3F的64个字节,刚好和要传送的数据0~63(3FH)一样,所以可以使用寄存器bx即表述偏移地址又表示要传送的数据。
程序如下(File:LabFour1.asm):
assume cs:code
code segment
mov ax,0020h
mov ds,ax
mov bx,0
mov cx,64
s: mov [bx],bl
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
说一下为什么是使用"mov [bx],bl"而不是"mov [bx],bx"。虽然在这题中两者看起来运行结果一样。因为ds:[bx]即0020:bx单元是一个字节单元(8位),而bx是一个16位寄存器,这就使得使用"mov [bx],bx"赋值时会对ds:[bx](8位)&(ds[bx+1])(8位)两个单元赋值。而当ds:[bx+1]时又会覆盖上一个ds[bx+1]的赋值,所以看起来运行结果是一样的。
我们实验一下把"mov [bx],bl"改成"mov [bx],bx",来验证上面的结果。
debug运行LabFour1.exe,并查看0020:0~0020:f内容
为方便观察把0020:0改为DD、0020:1改为FF、0020:2~0020:F中的内容全部改为0。
用t命令单步运行程序到"mov [bx],bx"
按道理来说我们只需要改变0020:0的内容为为00,我们可以发现运行前的0020:1内存是FF,运行"mov [bx],bx"之后就变成了00。"mov [bx],bx"将把bx中的数据(0000)送入内存0020:0000处。指令执行后,0020:0000单元的内容为00,0020:0001单元的内容为00。这就验证了上面所说的。
在来运行一下,"mov [bx],bx"将把bx中的数据(0001)送入内存0020:0001处。指令执行后,0020:0001单元的内容为01,0020:0002单元的内容为00。
所以运行结果看起来是一样的。
这是在小端模式的机器下运行没什么问题,但是在大端模式的机器下运行就有很大的问题。
某些机器选择在内存中按照从最低有效位到最高有效位的顺序存储对象,而另一个些机器则按照从最高有效位到最低有效位的顺序存储。
前一种规则——最低有效位在最前面的方式,称为小端法(little endian)。
后一种规则——最高有效位在最前面的方式,称为大端法(big endian)。
假设变量x的类型为int,位于地址0x100处,它的十六进制值为0x01234567。地址范围0x100~0x103的字节顺序依赖于机器的类型:
大端法
小端法
上面的程序在小端法上运行是这样子的(我的机器就是小端法,所以上面运行起来就是小端法)
大端法是这样子的
可以发现运行到最后就全是00,就有问题。
而用8位的bl,"mov [bx],bl"就不会。
3
下面的程序的功能是将“mov ax,4c00h”之前的指令复制到内存0~0:200处,补全程序。上机调试,跟踪运行结果。
程序如下(File:LabFour2.asm):
assume cs:code
code segment
mov ax,_(1)_
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,_(2)_
s:
mov al,[bx]
mov es:[bx],al
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
提示:
(1)复制的是什么?从哪里到哪里?
答:复制的是程序的指令,从"mov ax,(1)“开始到"loop s”。
(2)复制的什么?有多少个字节?你如何知道要复制的字节的数量
复制的是程序的指令,先运行程序,根据CX寄存器的值知道程序的长度(字节)。然后在减去从"mov ax,4c00h"指令开始的程序长度。
(1空):cs。
根据题意将“mov ax,4c00h”之前的指令复制到内存0~0:200处。根据程序上下文已经有0020所以ax=“程序的开头处地址”,即ax=cs。cs寄存器存放代码段寄存器。
(2空):23。
我们先让(2空)为2即mov cx,2,debug运行程序
我们可以发现
CX=001CH
从“mov ax,4c00h”开始的指令的机器指令是B8 00 4C CD 21,占了5个字节。所以在本实验中我们要复制的代码字节数为001CH-0005H=0017H=23个字节,故CX赋值为23或17H
修改代码,得出最终程序。
程序如下(File:LabFour2.asm):
assume cs:code
code segment
mov ax,cs
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,23
s:
mov al,[bx]
mov es:[bx],al
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
运行前的0020:0内容
运行程序后的0020:0内容
可以看到把程序复制过去了。