#pragma once
/*34-更灵活定位内存地址03
SI和DI
SI和DI是8086CPU中和BX功能相近的寄存器,但是SI和DI不能够分成两个8 位寄存器来使用。 (就是不能像AX,BX,CX,DX 通用寄存器一样 拆分出高位和低位)
SI和DI是又叫-- (SI)源变址寄存器 和 (DI)目的变址寄存器,其作用就是用来存放"偏移地址"的,所以说是和BX功能相近的寄存器,而且这两个也是通用寄存器,只是不能拆分成8位寄存器而已,注意从这里开始我们就已经学习
了6个通用寄存器了!!!
下面的三组指令实现了相同的功能:
(1) mov bx,0
mov ax,[bx]
(2) mov si,0
mov ax,[si]
(3) mov di,0
mov ax,[di]
下面的三组指令也实现了相同的功能:
(1) mov bx,0
mov ax,[bx+123]
(2) mov si,0
mov ax,[si+123]
(3) mov di,0
mov ax,[di+123]
问题
用寄存器SI和DI实现将字符串‘welcome to masm!’复制到它后面的数据区中。
assume cs:codesg,ds:datasg
datasg segment
db 'welcome to masm!'
db '................'
datasg ends
问题分析
我们编写的程序大都是进行数据的处理,而数据在内存中存放,所以我们在处理数据之前首先要搞清楚数据存储在什么地方,也就是说数据的内存地址。
现在我们要对datasg 段中的数据进行复制,我们先来看一下要复制的数据在什么地方,datasg:0,这是要进行复制的数据的地址。
那么复制到哪里去呢?
应该是复制到它后面的数据区。
因为 “welcome to masm!”从偏移地址0开始存放,长度为 16 个字节,所以,它后面的数据区的偏移地址为 16 ,就是字符串所要存放的空间。
清楚了地址之后,我们就可以进行处理了。
我们用ds:si 指向要复制的源始字符串,用 ds:di 指向复制的目的空间,然后用一个循环来完成复制。
SI和DI
代码段:
codesg segment
start: mov ax,datasg
mov ds,ax
mov si,0
mov di,16
mov cx,8
s: mov ax,[si]
mov [di],ax
add si,2
add di,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
注意,在程序中,我们用16位寄存器进行内存单元之间的数据传送,一次复制 2 个字节,一共循环8次。
问题
用更少的代码,实现上一个问题的程序。
思考后看分析。
联系上节课的方法。
问题分析
我们可以利用[bx(si或di)+idata]的方式,来使程序变得简洁。
程序如下:
codesg segment
start: mov ax,datasg
mov ds,ax
mov si,0
mov cx,8
s: mov ax,0[si]
mov 16[si],ax
add si,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
[bx+si]和[bx+di]
在前面,我们用[bx(si或di)]和[bx(si或di)+idata] 的方式来指明一个内存单元,我们还可以用更灵活的方式:
[bx+si]
[bx+di]
[bx+si]和[bx+di]的含义相似,我们以[bx+si]为例进行讲解。
[bx+si]表示一个内存单元,它的偏移地址为(bx)+(si)(即bx中的数值加上si中的数值)。
我们看下指令mov ax,[bx+si]的含义:
将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为bx中的数值加上si中的数值,段地址在ds中。
指令mov ax,[bx+si]的数学化的描述为:
(ax)=( (ds)*16+(bx)+(si) )
该指令也可以写成如下格式(常用):
mov ax,[bx][si]
问题
用Debug查看内存,结果如下:
2000:1000 BE 00 06 00 00 00 ……
写出下面的程序执行后,ax、bx、cx中的内容。
mov ax,2000H
mov ds,ax
mov bx,1000H
mov si,0
mov ax,[bx+si]
inc si
mov cx,[bx+si]
inc si
mov di,si
add ax,[bx+di] ; 思考后看分析。
分析
mov ax,[bx+si]
访问的字单元的段地址在ds中,(ds)=2000H;
偏移地址=(bx)+(si)=1000H;
指令执行后(ax)=00BEH。
mov cx,[bx+si]
访问的字单元的段地址在ds中,(ds)=2000H;
偏移地址=(bx)+(si)=1001H;
指令执行后(cx)=0600H。
add cx,[bx+di]
访问的字单元的段地址在ds中,(ds)=2000H;
偏移地址=(bx)+(di)=1002H;
指令执行后(cx)=0606H。
[bx+si+idata]和[bx+di+idata]
指令mov ax,[bx+si+idata]:
该指令也可以写成如下格式(常用):
mov ax,[bx+200+si]
mov ax,[200+bx+si]
mov ax,200[bx][si]
mov ax,[bx].200[si]
mov ax,[bx][si].200
问题
用Debug查看内存,结果如下:
2000:1000 BE 00 06 00 6A 22 ……
写出下面的程序执行后,ax、bx、cx中的内容。
mov ax,2000H
mov ds,ax
mov bx,1000H
mov si,0
mov ax,[bx+2+si]
inc si
mov cx,[bx+2+si]
inc si
mov di,si
mov bx,[bx+2+di] 思考后看分析。
问题分析
mov ax,[bx+2+si]
访问的字单元的段地址在ds中,(ds)=2000H;
偏移地址=(bx)+(si)+2=1002H;
指令执行后(ax)=0006H。
mov ax,[bx+2+si]
访问的字单元的段地址在ds中,(ds)=2000H;
偏移地址=(bx)+(si)+2=1003H;
指令执行后(cx)=006AH。
mov ax,[bx+2+si]
访问的字单元的段地址在ds中,(ds)=2000H;
偏移地址=(bx)+(si)+2=1004H;
指令执行后(cx)=226AH。
*/