第16章 直接定址表
16.1描述了单位长度的标号
assume cs:code
code segment
a db 1,2,3,4,5,6,7,8
b dw 0
start:
mov si,0
mov cx,8
s:
mov al,a[si]
mov ah,0
add b,ax
inc si
loop s
mov ax,4c00h
int 21h
code ends
end start
在code段使用的标号a、b后面没有“:”,它们是同时描述内存地址和单元长度的标号。所以,在指令中,它可以代表一个段中的内存单元。比如,对于上述程序中的b dw 0 ,标号b代表了一个内存单元,地址为code:8,长度为两个字节。
指令: mov ax,b
相当于:mov ax,cs:[8];
指令: mov b,2
相当于:mov word ptr cs:[8],2。
以后,我们将这种标号称为数据标号,它标记了存储数据的单元的地址和长度。它不同于仅仅表示地址的地址标号。
16.2在其他段中使用数据标号
可以将数据标号当作数据来定义,此时,编译器将标号所表示的地址当作数据的值。
比如:
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw a,b
data ends
数据标号c处存储的两个字型数据为标号a、b的偏移地址。相当于:
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw offset a, offset b
data ends
再比如:
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dd a,b
data ends
数据标号c处存储的两个双字型数据为标号a的偏移地址和段地址、标号b的偏移地址的段地址
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw offset a,seg a,offset b,seg b
data ends
16.3直接定址表(以下跳过)
P306
16.4 程序入口地址的直接定址表
我们可以在直接定址表存储子程序的地址,从而方便地实现不同子程序的调用。
下面的程序在调前,设置ah的值,如果为0则清屏。1则设置前景色,2设置背景色,3表示向上滚动一行。
assume cs:code
code segment
start:
setscreen:
jmp short set
table dw sub1,sub2,sub3,sub4
set:
push bx
cmp ah,3
ja sret
mov bl,ah
mov bh,0
add bx,bx;根据ah的功能号计算对应子程序在table表的偏移
call word ptr table[bx];调用对应的功能子程序
mov ax,4c00h
int 21h
sret:pop bx
ret
sub1:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
sub1s:
mov byte ptr es:[bx],' '
add bx,2
loop sub1s
pop es
pop cx
pop bx
ret
sub2:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub2s:
add byte ptr es:[bx],11111000b
or es:[bx],al
add bx,2
loop sub2s
pop es
pop cx
pop bx
ret
sub3:
push bx
push cx
push es
mov cl,4
shl al,cl
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub3s:
and byte ptr es:[bx],10001111b
or es:[bx],al
add bx,2
loop sub3s
pop es
pop cx
pop bx
ret
sub4:
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160;ds:si指向第n+1行
mov di,0
cld
mov cx,24;共复制24行
sub4s:
push cx
mov cx,160
rep movsb
pop cx
loop sub4s
sub4s1:
mov byte ptr [160*24+si],' '
add si,2
loop sub4s1
pop ds
pop es
pop di
pop si
pop cx
ret
code ends
end start