今天我们继续看第五章。
两个约定
我们先讲一下,作者有两个约定:
为了描述上的简洁,在以后的课程中,我们将使用一个描述性的符号“()”来表示一个寄存器或一个内存单元的内容。
用idata表示某个常量
所以我们这里沿用这两个记号。
[BX]
首先我们先来看一下[BX]。
这个是什么?
大家应该还记得[address]吧?
我们当时的这个是用来指定偏移地址的。
所以,我们这里也是这样。
其实就是用bx中的内容去指定偏移地址。
我们来看个例子:
mov ax,[bx]
这句是什么意思呢?
其实,就是:
((ds)*16+(bx))=(ax)
这里用到了作者之前的记号,大家应该很容易的能理解,这和[address]是一样的。
这里提示一点,我们的bx并不能换成ax或者cx等其他寄存器,也就是说我们在中括号中只能放置bx。
这个作者虽然没有这么说,但是我上网查了一下,并没有出现类似字眼(如:[AX]),而且我也写程序试了一下,试试证明如果用[AX],编译器会报错的。
loop
下面我们看一下loop指令。
loop在英文中的意思是“循环”(可见英语的重要性),所以我们这里loop也是用来起到循环功能的。
具体的语法如下:
loop [记号]
记号是什么意思?
如果你学过C或C++,或者你听说过“goto”的话,可能比较熟悉记号是什么。
记号没有限定,你可以自己随便取,但是不能和保留字(就是系统的一些指令,如:mov、add等,为了不产生混乱)相同,至于怎么用,我过会举个例子各位就明白了。
那么,loop怎么工作的呢?
执行loop时,会先后进行两步运算:
- (cx)=(cx)-1
- 判断CX中的值,不为零则转至标记处执行程序,如果为0则向下执行
注意两步操作的先后顺序
这就是loop的工作过程。
那么我们怎么用呢?
看下面这段代码:
assume cs:cgg
cgg segment
mov cx,200
fxx:add ax,2
loop fxx
mov ax,4c00H
int 21H
cgg ends
end
这里起到的就是一个循环的作用,相信大家也很容易理解。
那么各位注意一下,我们会发现,loop用的是cx中的值,而不是其他的值。
这里和[BX]一样,是特指的,不能更换的。
debug和编译器的一个小差异
其实也不小了。
那就是对[idata]的理解。
比如我们有这么一个语句:
mov ax,[0]
debug和编译器对这句话的理解是不同的。
debug认为是将ds:0000的数据移入ax。
而编译器则不同,它认为是这样的:
mov ax,0
即它会视[idata]为idata。
那么我们要怎么在编译源文件中实现从内存中取数呢?
三种方法:
mov al,[bx]
mov al,ds:[0]
mov al,ds:[bx]
这样就可以了。
段前缀
所谓段前缀,就是指我们在指明内存单元时,使用的段地址。
如:
mov ax,ds:[bx]
mov ax,cs:[bx]
mov ax,ss:[bx]
mov ax,ex:[bx]
没错,你没看错,这些都可以作为段地址。
而这里的“ds:”、“cs:”、“ss:”、“es:”就是段前缀。
指令补充
inc 寄存器
这句语句其实就是++的意思,使某个寄存器中的值加一。
这个语句同样也不能对特殊的寄存器操作
第五章就到这里了。