汇编——存储器取数据和地址跳转的寻址方式

前言

在编写汇编代码的时候,我们经常需要取出各种各样的数据,进行操作,
但是有的数据常数(这里叫立即数),还有的在寄存器中,都是很简单的,但是难免有一些在存储器中,这时我们就需要取出数据进行操作。

在分支结构或者循环结构中,我们可能需要跳过几行(if else语句)或者回到几行之间(循环),
所以我们需要修改存储当前指令的IP寄存器,为其赋值的过程中我们就需要赋值,道理同上。

在例子中,我们经常使用的是mov ax,……,这里要说明一下,寻址方式不一定非要是mov指令,而且mov指令这样的两个操作数都可以采用寻址方式。

寻址的准备工作

先讲一下地址的形成:
8086是20位的地址线,但是我们的寄存器是16位的,剩下的四位不能浪费了,所以人们就想出附加段寄存器的方式(下面的配对中,前面的都是附加段寄存器)。
将附加段寄存器的内容乘10H,然后加上偏移地址(EA),这样我们就得到了一个20位的地址。
我们将20位的地址叫做物理地址(PA)。
接下来需要求的就是EA。

给出常用的寄存器配对:

  • CS+IP
  • SS+SP or BP
  • DS+BX、DI、SI或一个16位数
  • ES+DI(用于串指令)

如果不是串部分,我们的DI寄存器都配合DS使用。

另外我们还有跨段寻址,就是不按照默认的寄存器来,如:MOV AX,DS:[BP]

立即数寻址和寄存器寻址

mov ax,10h
mov ax,bx
一个是将10h的内容赋值给ax,另一个是将bx的内容赋值给ax。
使用立即数或者是寄存器的数据赋值,都不需要在存储器中寻找数据,还是很快的。

五种存储器寻址方式

在这里插入图片描述
寻址说白了就是从一个有效地址中读取一个数据,赋值给对象(或者是将数据赋值给地址指向的地方)

直接寻址

mov al,[1000h]
直接将地址给出,然后我们将地址对应的内容赋值给al寄存器(不是直接塞地址过去)

我们经常使用一个符号来代替地址常数,所以可以写成:
mov ax,[buffer]或者mov ax,buffer

注意这里的buffer为偏移地址,我们还需要加上附加段地址(默认为DS),如果有跨段,则按照给出的段来就好。

注意区分一下mov ax,[1000h]和mov ax,1000h

寄存器间接寻址

间接就是不直接给出显式地址,而是存在寄存器中,我们需要自己去算有效地址(当然是计算机帮你算了)。
格式:mov ax,[bx] ,
这里能使用的寄存器只有几个:BX 、BP、SI、DI,只需要匹配默认的段寄存器然后算出20位地址,将地址上的数据送进ax就行。

例:
MOV BX, [DI],(DS)=1000H,(DI)=2345H
所以我们得到了一个12345h的地址,将地址的内容取出来,给bx就行。

区分mov ax,bx

寄存器相对寻址

相对,我们可以想象成一个数组,我们只知道其首地址是不能直接得到我们想要的内容,所以我们需要有一个相对地址来找到元素。

格式:mov ax,[bx+60h]或mov ax,60h[bx]
这里面的常数我们叫做偏移量,为八位或者十六位(注意是有符号数)
找到对应的附加段,然后将60h也加到物理地址上,得到我们最终的地址,然后取值、赋值即可。

这里我们区分一下四个寄存器,接下来会用到
基址寄存器:BX、BP
变址寄存器:SI、DI

基址变址寻址方式

MOV BX, [BX+SI]
这里我们需要用到一个基址寄存器和一个变址寄存器,将两者求和再加上对应的段寄存器就能找到物理地址。
那么我们是使用哪个寄存器的对应段寄存器呢?
解释一下两个寄存器的定义:

用基址表示首地址,
而用变址来表示数组,表格或者字符串中的某一个值

很明显,我们应该采取的是基址寄存器对应的段寄存器。

一直在用数组举例子,其实寄存器相对寻址和基址变址寻址是可以联系上一维数组的。

相对基址变址寻址方式

格式:MOV AX, [BX+SI+200H],(或者200H[BX+SI])
就是基址加变址加偏移量形成的地址。

那这个应该代表什么呢?
二维数组,
基址为首地址,变址确定哪一行,偏移地址确定哪一个位置,求和后还要加上附加段地址,然后就可以得到PA了。

总结

  1. 间接就是隐晦,就是不直接给出,需要我们自己读取一下;
  2. 相对就是有常数偏移量,变址就是要加上一个寄存器的内容(也算是偏移量),相当于一维数组
  3. 相对基址变址就是二维数组,首地址+变址+偏移量
  4. 寄存器操作数地址只能由BX、BP、SI、DI 给出, 它们的组合也不是任意的。

转移指令寻址

就是修改当前的指令地址(IP寄存器中),赋值方式和上面差不多

段内转移

分为直接和间接,也就是是否直接给出地址。

如果是直接转:JMP short next(next为结束在的位置,是一个地址)
short是8位位移量,near ptr是16位。(不是结束地址)
JMP是跳转指令。
虽然我们是直接给出跳转地址的位置,但是在机器指令中(我们写的是伪指令)显示的是位移量,也就是差值。

间接跳转的话,我们采取的是JMP word ptr +间接寻址。
这里的形式不止一种,比如JMP [BP]和JMP [BX][SI]都是有的。

这里我们添加word ptr的目的是因为我们需要在后面给出的地址中取值,其中取值的类型需要确定。
可能有一点绕,想一下我们的目的就是取出一个地址,而我们采用的是间接,所以就是找到一个地址,从该地址上取我们需要的地址。(地址为一个字的大小)
然后我们在找到地址之后,我们需要取出一个字的内容,作为我们跳转的目的地,但是如果是jmp+间接地址,其实计算机是不知道我们想取出的数据的类型的,这里就需要加上word ptr告诉计算机我们要取一个字的大小。

但如果是寄存器间接寻址,我们直接拿出寄存器的地址,可以确定大小是一个字,所以word ptr就不需要了。

段间转移

段内是只修改IP,如果是段间转移,我们则需要修改CS和IP。
也是分为直接和间接。

直接:在给出的物理地址,我们读取出偏移地址和附加段地址,分别赋值给IP和CS就行了。
怎么读?我们有指令的。

  • offset +物理地址 得到偏移地址给IP
  • seg +物理地址 得到附加段地址给CS

如果是段间间接寻址,那么我们需要先找到一个物理地址,还是采取读数的方式。
不过之前都是寄存器为几位就读取几位,这次我们采取不一样的方式。

例子:DS=3000H,BX=1200H,INTERS=0020H
JMP DWORD PTR [INTERS+BX]
我们得到的地址为31220h,然后在内存中寻找该地址:
在这里插入图片描述
从高到低,一共是8个16位数,先四个给CS,然后是IP。

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值