1. 内存单元作为第一个操作数或唯一的操作数时的情形:
1) 前面讲过当内存访问作为第一个操作数时不能使用之前说过的法则,即使第二个操作数是寄存器也不行;
2) 这个时候就需要显式指明内存单元的类型了,可以使用byte ptr或word ptr操作符来指明内存单元是字节型的还是字型的;
!注意:这两个操作符是编译器提供的操作符,并不是汇编指令,不能直接一步翻译成二进制码;
3) 使用的情形:
i. 首先是第一个操作数必须是内存单元;
ii. 第二个操作数可以是寄存器或立即数,不能两个操作数都是内存单元,否则会报错的!
iii. 如果指令是单操作数时也行;
!注意:即使第一个操作数是寄存器而第二个是内存也可以使用,但是不建议这样做,因为这种情况是可以自动推断的,不要多此一举;
4) 示例:
assume cs:code
code segment
mov byte ptr [bx], 12
add word ptr [3FH + bp], cx
sub byte ptr [bp][si][9H], cl
and word ptr 0FCH[bx], 1001B
or byte ptr [bp + 9], bh
inc word ptr [bx]
mov ax, 4C00H
int 21H
code ends
end
!注意:还是不能将[立即数]作为第一个操作数,编译器会将其理解成一个立即数看待的!
4. 除法指令div:
1) 可以把div看做是mul的逆运算,因此div也有两种类型,分别对应着mul的两种类型;
2) 对应于字节型的mul,div的运行方式是,将被除数放在ax(mul的结果),除数放在8位寄存器或内存中,商默认存放在al中(mul的第一个默认乘数),而余数放在ah中;
3) 对应于字型的mul,被除数的低位放在ax中高位放在dx中(mul的结果),除数放在16位寄存器或内存中,商默认放在ax中(mul的第一个默认乘数),而余数放在dx中;
4) div使用方法,先对数据范围进行估计,然后执行上述步骤(即准备被除数和除数),最后直接执行"div 除数"指令即可,结果就保存在相应的寄存器中了;
5) 实例:1001 / 100和100001 / 100:
assume cs:code
code segment
mov ax, 1001
mov bl, 100
div bl
mov ax, 86A1H
mov dx, 1H
mov bx, 100
div bx
mov ax, 4C00H
int 21H
code ends
end
运行结果:
*1. 商是0AH,余数是1H
*2. 商是3E8H,余数是1H
5. 定义双字型数据的伪指令——dd:
a. 即define double word,可以定义双字型数据(32位);
b. 程序示例——将第一个数除以第二个数的商放在第三个数中:
assume cs:code, ds:data
data segment
dd 100001
dw 100
dw 100
data ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, ds:[0]
mov dx, ds:[2]
div word ptr ds:[4]
mov ds:[6], ax
mov ax, 4c00h
int 21h
code ends
end start
a. 使用规则:db/dw/dd 重复次数 dup (数值列表)
b. 即将数值列表中的数值重复定义n次,比如:
db 3 dup (1, 2, 3)
即将字节型数值1, 2, 3重复定义3次,即定义了1, 2, 3, 1, 2, 3, 1, 2, 3这9个字节数据
7. 一个较长的程序:
i. 将年份、收入、雇员数、平均收入填入table表中;
ii. 程序如下:
assume cs:code, ds:data
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11452,14430,15257,17800
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, table
mov ss, ax
mov bx, 0
mov si, 168
mov bp, 0
mov cx, 21
s:
;done year
mov ax, [bx + 0]
mov [bp + 0], ax
mov ax, [bx + 2]
mov [bp + 2], ax
;done n
mov ax, [si]
mov [bp + 10], ax
;done sum
mov ax, [bx + 84]
mov [bp + 5], ax
mov dx, [bx + 86]
mov [bp + 7], dx
;done avg
div word ptr [bp + 10]
mov [bp + 13], ax
add bx, 4
add si, 2
add bp, 10h
loop s
mov ax, 4c00h
int 21h
code ends
end start
iii. 程序运行结果如下: