多种寻址方式定位内存地址

当数据存放在内存中时,我们可以使用多种方式来给定这个内存单元的偏移地址,这种定位内存单元的方法被称为寻址方式。
这里写图片描述

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.为什么我们需要这么多的寻址方式

这是为了在效率和方便性上找一个平衡。立即数寻址和寄存器寻址在效率上是最快的,但寄存器仅有几个非常宝贵不可能将操作数都存入其中等待使用,立即数的使用场合也非常有限,这样就需要将数据保存在内存中,然后使用直接寻址、寄存器间接寻址、寄存器相对寻址、基址加变址寻址、相对基址加变址寻址这些寻址方式将内存中的数据移入寄存器中。
(摘自http://m.blog.csdn.net/article/details?id=6911132

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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值