引入段前缀:一个“异常”现象及对策
-
Debug中,mov al,[0]的功能是——将Ds:0存储单元的值传给AL
-
编译好的程序中,mov al,[0]变成了将常量0传给AL
-
对策:在[idataj前显式地写上段寄存器
mov ax,2000h mov ax,2000h
mov ds,ax mov ds,ax
mov bx,0 mov al,ds:[0]
mov al,ds:[bx]
- 小结(在程序中)
mov al,[0]: (al)=0,同mov al,0
mov al,ds:[0]: (al)=((ds)*16+0)
mov al,[bx]: (al)=((ds)*16+(bx))
mov al,ds:[bx]: 与mov al,[bx]相同
- 这些出现在访问内存单元的指令中,用于显式地指明内存单元的段地址的“ds:”“cs:”“ss:”或“es:”在汇编语言中称为段前缀。
访问连续的内存单元——loop和[bx]联手
-
问题:计算ffff:O~ffff:竞节单元中的数据的和,结果存储在中
-
分析∶
-
运算后的结果是否会超出dx所能存储的范围?
ffff:0ffff:b内存单元中的数据是字节型数据,范围在0255之间,12个这样的数据相加,结果不会天于65535,可以在dx中存放下。 -
是否可以将ffff:0 ~ffff:b中的数据直接累加到dx中?
add dx,ds[addr] ;(dx)=(dx)+?
期望∶取出内存中的8位数据进行相加
实际:取出的是内存中的16位数据
-
是否可以将ffff:0 ~ ffff:b中的数据直接累加到dl中?
add dl,ds:[addr] ;(dl)=(dl)+?
期望:取出内存中的8位数据相加
实际:取出的是内存中的8位数据,但很有可能造成进位丢失。
-
-
对策:取出8位数据,加到16位的寄存器
mov al, ds:[addr]
mov ah, 0
add dx, ax
程序:计算ffff:O~ffff:b单元中的数据的和,结果存储在dx中
assume cs:code
code segment
mov ax,Offffh
mov ds,ax
mov dx,0
mov al,ds:[0]
mov ah,0
add dx,ax
mov al,ds:[1]
mov ah,0
add dx,ax
mov al,ds:[2]
mov ah,0
add dx,ax
mov al,ds:[3]
mov ah,0
add dx,ax
mov al,ds:[4]
mov ah,0
add dx,ax
mov al,ds:[5]
mov ah,0
add dx,ax
mov al,ds:[6]
mov ah,0
add dx,ax
mov al,ds:[7]
mov ah,0
add dx,ax
mov al,ds:[8]
mov ah,0
add dx,ax
mov al,ds:[9]
mov ah,0
add dx,ax
mov al,ds:[0ah]
mov ah,0
add dx,ax
mov al,ds:[0bh]
mov ah,0
add dx,ax
mov ax,4c00h
int 21h
code ends
end
- 改进
- 用loop循环
- 方法
- 循环次数电CX控制
- 循环中要访问的内存单元的偏移地址放到中,随循环递增,访问连续的内存单元。
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax
mov bx,0
mov dx,0
mov cx,12
s: mov al,[bx]
mov ah,0
add dx,ax
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
段前缀的使用
- 问题:将内存ffff:0ffff:b中的数据拷贝到0:2000:20b单元中
;初始方案
assume cs:code
code segment
mov bx,0
mov cx,12
s:mov ax,0ffffh
mov ds,ax
mov dl,[bx]
mov ax,0020h
mov ds,ax
mov [bx],dl
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
;使用附加段寄存器
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,12
s:mov dl,[bx]
mov es:[bx],dl
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end