1. 预备知识
- 先前,我们在代码段中使用标号来标记指令、数据或段的起始地址,这类标号仅仅表示内存单元的地址。我们还可以使用一种标号,这种标号不但表示内存单元的地址,还表示了内存单元的长度。
a db 1,2,3,4,5,6,7,8
b dw 0
- 上述标号 a 和 b 后面没有冒号,它们同时描述内存地址和单元长度。如标号 a 描述了地址 code:0,和从这个地址开始以后的内存单元都是字节单元;标号 b 描述了地址 code:8,和从这个地址开始以后的内存单元都是字单元。
- 因为这种标号包含内存单元的长度,所以可以借由它表示段中内存单元的地址。如:
mov ax,b 相当于 mov ax,cs:[8]
mov b,2 相当于 mov word ptr cs:[8],2
inc 相当于 inc word ptr cs:[8]
- 一般情况下,我们不在代码段中定义数据,而是将数据定义到其他段。如果想在代码端中直接用数据标号访问数据,需使用 assume 将标号所在段与一个段寄存器联系起来。
assume cs:code,ds:data
data segment
a ab 1,2,3,4,5,6,7,8
b dw 0
data ends
start:
mov ax,data
mov ds,ax
...
mov al,a[si] ;使用标号访问数据,与段寄存器DS相关联
...
add b,ax ;使用标号访问数据,与段寄存器DS相关联
...
- 还可以将标号当作数据来定义,此时编译器将标号所表示的地址当作数据的值。
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw a,b
data ends
相当于
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw offset a,offset b
data ends
2. 检测点 16.1
下面的程序段将 code 段中 a 处的 8 个数据累加,结果存储到 b 处的 dword 中,补全程序。
assume cs:code
code segment
a dw 1,2,3,4,5,6,7,8
b dd 0
start:
mov si,0
mov cx,8
s:
mov ax,____
add ____,ax
adc ____,0
add si,____
loop s
mov ax,4c00h
int 21h
code ends
end start
- 标号 a 描述单元 cs:0,从这个单元开始,后面单元都是字单元;标号 b 描述单元 cs:10,从这个单元开始,后面单元都是双字单元。
- 程序中包括 add 和 adc 两种加法指令,add 用于累加 a 处的数据、adc 用于处理进位数据。b 为双字单元,使用 b[0] 存储相加内容、b[2] 存储进位内容:
add word ptr b[0],ax
adc word ptr b[2],0
- 由于 a 定义的是子单元,所以 si 每次偏移 2 个字节。
add si,2
整体代码为:
assume cs:code
code segment
a dw 1,2,3,4,5,6,7,8
b dd 0
start:
mov si,0
mov cx,8
s:
mov ax,a[si]
add word ptr b[0],ax
adc word ptr b[2],0
add si,2
loop s
mov ax,4c00h
int 21h
code ends
end start
程序运行前,查看标号 a 和 标号 b 内存单元的内容。
程序运行后,查看标号 b 内存单元的内容。
此时,标号 b 的内容为 00000024h,为标号 a 单元的内容和。
3. 检测点 16.2
下面的程序段将 code 段中 a 处的 8 个数据累加,结果存储到 b 处的 dword 中,补全程序。
assume cs:code,es:data
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
data ends
code segment
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
- 标号 a 描述单元 ds:0,从这个单元开始,后面单元都是字节单元;标号 b 描述单元 ds:8,从这个单元开始,后面单元都是字单元。
- mov al,a[si] 默认使用的段地址是数据段所在地址,且 assume 中 es 与 data 段相关联,缺失部分语句使用段寄存器 ES 指向 data 段:
mov ax,data
mov es,ax
整体代码为:
assume cs:code,es:data
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
data ends
code segment
start:
mov ax,data
mov es,ax
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
程序运行前,查看标号 a 和 标号 b 内存单元的内容。
程序运行前,查看标号 b 内存单元的内容。
此时,标号 b 的内容为 0024h,为标号 a 单元的内容和。
4. 总结
- 标号除用于表示指令、数据或段的地址,还可以表示内存单元的长度。前者标号后面带冒号,后者不带冒号。
- 在其他段中使用标号表示的数据时,需通过 assume 伪指令将标号所在段与某个段寄存器相关联。且在程序中,也要实现该关联。