loop在汇编里面是执行循环的意思
[bx]是什么?
和[0]有些类似,[0]表示内存单元,他的偏移地址是0。
比如在debug中
mov ax,[0]
将一个内存单元的内容送入ax,这个内存单元的长度为2字节,存放一个字,偏移地址为0,段地址在ds中。
mov al,[0]
将一个内存单元的内容送入al,这个内存单元的长度为1字节,存放一个字节,偏移地址为0,段地址在ds中。
要完整的描述一个内存单元,需要两种信息:
- 内存单元的地址
- 内存单元的长度(类型)
[bx]也表示一个内存单元,他的偏移地址在bx中,比如
mov ax,[bx]
将一个内存单元的内容送入ax,存放一个字,偏移地址在bx中,段地址在ds中。
但是debug和masm对代码的编译执行不太一样
明明我代码想传输的偏移地址,到了debug里面就变成了数据
所以我们可以这么写:
mov bx,0
mov ax,[bx]
loop指令
指令格式:loop 标号,CPU执行loop时要进行两步操作
- (cx)=(cx)-1
- 判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。
loop和cx紧密相连,cx影响loop的执行结果。
这段我自己写了代码的,,要学自己看书哈。
loop是循环的意思
cx里面存放循环的次数
debug和汇编编译器masm对指令的不同处理
我们在debug中写过一个指令
mov ax,[0]
表示讲ds:0处的数据送入ax中
但是在汇编程序中,指令mov ax,[0]被编译器当作指令“mov ax,0”处理了。
所以一般我们用如下指令哈
mov bx,1
mov ax,[bx]
如果想在调试的时候跳过循环,那你直接就用p指令可以跳过,如下
也可以直接用g指令跳过,如下:就是先用u指令看看,loop的下一步指令是在哪个地址里面,然后用g直接干那个地址就行了。
举个例子吧
mov al, [0] //将0赋值给al
mov al, ds:[0] //将段地址为ds,偏移地址为0单元的内容放到al中
mov al, [bx] //将默认段地址为ds,偏移地址为bx的内容,放到al中
mov al, ds:[bx] //跟第三段一样的。
安全空间
我们在往地址里面写数据时,要看看地址里是不是有别的应用程序或者系统的代码。
在一般的PC机中,DOS方式下,DOS和其他合法程序一般都不会使用0:200~0:20b的256个字节的空间,所以我们使用这段空间是安全的。
以后我们直接向一段内存写入内容的时候,就使用这段空间
段前缀
我们考虑一个问题:将内存ffff:0~ffff:b的内容放到0:200~0:20b中。
- 0:200~0:20b等同于0020:0~0020:b单元,他们描述的是同一段内存空间。
- 拷贝的过程要用循环实现,简要描述
初始化X=0
循环12次
将ffff:X的数据送入0020:X(需要一个寄存器中转)
X=X+1
- 在循环中,原单元ffff:X和目标单元的0020:X的偏移地址X是变量。我们用bx存放
- 我们用0020:0~0020:b的描述,就是为了使目标单元的偏移地址和原始单元的偏移地址从同一数值0开始。 ```c assume cs:code
code segment mov bx,0 mov cx,12
s: mov ax,0ffffh //设置段地址 mov ds,ax
mov dl,[bx] //把当前段地址为0ffffh,偏移地址为bx的内容放到dl中
mov ax,0020h //设置段地址为0020h
mov ds,ax
mov [bx],dl //把dl中的内容存到段地址为0020h,偏移地址为bx的单元中
inc bx //bx自加一
loop s //循环
mov ax,4c00h
int 21h
code ends end
因为ffff:X和目标单元0020:X相距大于64KB,在不同的64KB段里,所以每次循环都要设置两次ds<br />这样做是对的,但是效率不高,<br />可以用两个段寄存器分别存放原单元和目标单元的段地址,以下为改进的代码,改进的程序中,使用es存放目标空间0020:0~0020:b的段地址,ds存放原空间ffff:0~ffff的段地址。
```c
assume cs:code
code segment
mov ax,0ffffh //设置第一个段地址
mov ds,ax
mov ax,0020h //设置第二个段地址为0020h
mov es,ax
mov bx,0
mov cx,12
s: mov dl,[bx] //把dl中的内容存到段地址为0020h,偏移地址为bx的单元中
mov es:[bx],dl
inc bx //bx自加一
loop s //循环
mov ax,4c00h
int 21h
code ends
end