多种寻址方式定位内存地址
当数据存放在内存中时,我们可以使用多种方式来给定这个内存单元的偏移地址,这种定位内存单元的方法被称为寻址方式。
1. 直接寻址
寻址方式:
[idata]
含义:
EA=idata
寻址过程:
例: 上图中的 mov ax,ds:[000E]
CS和IP中的地址通过地址加法器进行移位相加得到代码的物理地址,通过地址总线进入内存,取出相应地址的机器码000EA1,通过数据总线传到指令缓冲寄存器,读取指令判断是直接寻址,则通过段地址ds和偏移地址[000E]得到数据的物理地址,在内存中取出。
2.寄存器间接寻址
寻址方式:
[bx]
含义:
EA=(bx)
寻址过程:
例: 上图中的 mov ax,[bx]
CS和IP中的地址通过地址加法器进行移位相加得到代码的物理地址,通过地址总线进入内存,取出相应地址的机器码078B,通过数据总线传到指令缓冲寄存器,读取指令判断是寄存器间接寻址,则通过段地址ds和寄存器BX提供的偏移地址得到数据的物理地址,在内存中取出。
3.寄存器相对寻址
寻址方式:
[bx+idata]
含义:
EA=(bx)+idata
寻址过程:
例: 上图中的 mov ax,[bx+1]
CS和IP中的地址通过地址加法器进行移位相加得到代码的物理地址,通过地址总线进入内存,取出相应地址的机器码01478B,通过数据总线传到指令缓冲寄存器,读取指令判断是寄存器相对寻址,则通过段地址ds和寄存器BX提供的内容加上一得到偏移地址从而得到数据的物理地址,在内存中取出。
4.基址变址寻址
寻址方式:
[bx+si] ; [bx+di]
含义:
EA=(bx)+(si) ; EA=(bx)+(di)
可以表示为[bx][si],相当于一个二维数组
寻址过程:
例: 上图中的 mov ax,[bx+si]
CS和IP中的地址通过地址加法器进行移位相加得到代码的物理地址,通过地址总线进入内存,取出相应地址的机器码008B,通过数据总线传到指令缓冲寄存器,读取指令判断是基址变址寻址,则通过段地址ds和寄存器BX提供的内容加上源寄存器SI提供的内容得到偏移地址从而得到数据的物理地址,在内存中取出。
5.相对基址变址寻址
寻址方式:
[bx+si+idata] ; [bx+di+idata]
含义:
EA=(bx)+(si)+idata ; EA=(bx)+(di)+idata
寻址过程:
例: 上图中的 mov ax,[bx+si+1]
CS和IP中的地址通过地址加法器进行移位相加得到代码的物理地址,通过地址总线进入内存,取出相应地址的机器码01408B,通过数据总线传到指令缓冲寄存器,读取指令判断是相对基址变址寻址,则通过段地址ds和寄存器BX提供的内容加上源寄存器SI提供的内容再加上一得到偏移地址从而得到数据的物理地址,在内存中取出。
6.为什么我们需要这么多的寻址方式
这是为了在效率和方便性上找一个平衡。立即数寻址和寄存器寻址在效率上是最快的,但寄存器仅有几个非常宝贵不可能将操作数都存入其中等待使用,立即数的使用场合也非常有限,这样就需要将数据保存在内存中,然后使用直接寻址、寄存器间接寻址、寄存器相对寻址、基址加变址寻址、相对基址加变址寻址这些寻址方式将内存中的数据移入寄存器中。
7.应用举例
问题1:编程将datasg段中每个单词的头一个字母改为大写字母。
assume cs:codesg,ds:datasg
datasg segment
db ‘1. file ’
db ‘2. edit ’
db ‘3. search ’
db ‘4. view ’
db ‘5. options ’
db ‘6. help ’
datasg ends
codesg segment
start: ….…
mov 4c00h
int 21h
codesg ends
end start
注意这里定义的字符串后面是有空格个,凑成的一行16个字节
直接寻址方式
[bx+idata] 起始bx设为0,为第一行第一个单元的地址,idata设为3,表示这一行第三个单元即单词首字母
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,6 ;循环六次
s: mov al,[bx+3]
and al,11011111b ;与运算,小写变成大写
mov [bx+3],al
add bx,16 ;bx加16,跳到下一行开始位置
问题2:编程将datasg段中每个单词改为大写字母
assume cs:codesg,ds:datasg
datasg segment
db ‘ibm ’
db ‘dec ’
db ‘dos ’
db ‘vax ’
datasg ends
codesg segment
start: ……
codesg ends
end start
注意这里定义的字符串后面是有空格个,凑成的一行16个字节
寄存器间接寻址二重循环
4 个字符串,可以看成一个 4行16列的二维数组,要修改二维数组的每一行的前3列,则构造4x3次的二重循环
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0: mov si,0
mov cx,3
s: mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s ;内层循环
add bx,16
loop s0 ;外层循环
但是这样做只有一个cx,执行完内层循环后就变成0了,无法完成外层循环
这里可以用栈保存cx
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
mov ax,stacksg
mov ss,ax
mov sp,16
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0: push cx ;将外层循环的cx值压栈
mov si,0
mov cx,3 ;cx设置为内存循环的次数
s: mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s
add bx,16
pop cx ;从栈顶弹出原cx的值,恢复cx
loop s0
还没有评论,来说两句吧...