zoukankan      html  css  js  c++  java
  • 8086CPU中的寻址方式一

    寻址方式

    定义

    寻址方式:求操作数所在地或者所在存储器地址单元的方式。

    指令中的操作数,大多数都在存储器单元当中,也可以在寄存器里面,也可以是在指令中立即给出的常数。我们都把求得她们的方式归属于寻址方式。


    类型

    寻址方式按求得的操作数的目的不同,可以分为两类:

    1. 数据用

    2. 程序要实现转移的地址用

    如果要实现段内转移,就需要求得段内偏移地址给IP用,如果要实现段间转移,除了偏移地址外,还需要求得目的地的段地址给CS用。

    要计算的数据的所在存储地址怎么得到,或者转移的地址内容的所在存储地址怎么得到,就需要用以一种寻址方式去求得。


    关于数据的寻址方式

    1.立即数寻址

    要寻找的操作数在指令中立即给出,直接以常数给出。

    mov AX,1234H
    

    AX是目的操作数,1234H是源操作数,对于源操作数而言,采用的就是立即数寻址。指令中要传送给AX的数据在哪里呢?指令中立即给出了。这就叫立即数寻址。

    要搞清楚8086立即寻址,就需要了解谁和谁之间可以传送

    从图中可知,在8086当中,立即数只能作为源操作数。

    立即数传送数据时要类型明确

    mov [0002H],15H
    

    中括号里面表示的是地址,这条语句是把立即数15H送到地址为0002H的存储器单元中。

    但是我们只知道地址是多少,不知道存储器单元的存储类型是什么?语法错误。类型不明确。这中问题只要源操作数和目标操作数有一方明确,双方均能明确(不一致另说)。双方不明确,类型不明确。

    mov WORD PTR [0002H],15H
    

    如果要传送数据给段寄存器,不能直接立即数传送,要按箭头走。

    从图中也可以看出,段寄存器CS单独划分出来,因为用户无法改变CS的内容,和IP寄存器一样,开机的内容由操作系统完成。执行期间是由CPU完成转移指令改变。CS和IP不能做目标操作数,但是可以做源操作数。


    2.寄存器寻址

    指要寻找的操作数在某寄存器当中

    mov AX,BX
    

    对于源操作数而言,要操作的数据在BX寄存器中,这就是寄存器寻址。同样的,目的操作数而言,也是寄存器寻址。

    当源和目标是寄存器寻址时,一定要注意类型要一致

    mov AX,CL
    

    AX是16位的,而CL是8位的,语法错误。


    3.存储器寻址

    指要寻找的操作数在存储器某单元中,存放操作数的单元的EA段内偏移地址,可以由以下5种寻址方式求得:

    1.直接寻址

    直接寻址就是在指令中直接写出存储单元的有效地址

    mov AL,[2000H]
    

    将存储器单元地址为2000H的字节内容送给AL(实际上决定是字节内容的是AL的类型)

    但这种方法不常用,一般都将地址符号化——变量名。

    在DS段有下列变量定义:

    dat1 DB 12H
    dat2 DB 34H
    ...
    

    实际中数据段定义的变量很多。

    在CS段执行程序

    mov AL dat1
    

    dat1代表的就是一个地址,所以源操作数的寻址方式是直接寻址。在dat1里面的内容送给AL。执行完(AL)=12H。

    mov dat2 dat1
    

    源和目标操作数都采用直接寻址,想把dat1里内容直接送给dat2单元里面。但是语法错误。如上图3.3,寄存器之间可以互传数据,但是存储器单元之间不可以直接操作(任何操作)。不能直接传送数据,也不能直接运算。

    只能通过寄存器做中转,读出来后,再将寄存器里面的值送给存储器。

    当然也要遵循前后类型一致。如

    mov WORD PTR dat1,AX
    

    而不能直接进行数据传送,因为dat1是字节变量8位,AX是16位。

    mov dat1,AX
    

    2.寄存器间接寻址

    指操作数在存储器中,段内偏移地址由寄存器间接给出。能做寄存器间接寻址的寄存器只有3个——BX,SI,DI。

    这三个寄存器默认的段地址默认在DS数据段

    dat1 DB 12H
    dat2 DB 34H
    

    把dat1内容送给AL,寄存器间接寻址方式为:

    mov BX, OFFSET dat1
    mov AL,[BX]
    

    OFFSET dat1把dat1的偏移地址属性拿出来了,所以对于源操作数而言属于立即数寻址。

    [BX]中括号里面是把BX的内容作为DS段的段内有效地址,属于寄存器间接寻址。


    3.寄存器相对寻址

    指的是操作数在存储器某个单元当中,有效地址由两部分组成:

    第一部分在一个基址寄存器当中——BX,BP,SI,DI 四者之一。第二部分是一个8位或16位的DISP相对位移量。两部分之和就是操作数所在存储单元的地址。

    如果相对位移量是一个常数,那么对应的逻辑段的段地址由寄存器部分默认决定给出。BXSIDI默认在DS段,BP默认在堆栈段SS。

    如果相对位移量是一个变量,会自动取变量的段内偏移地址作为位移量,此时逻辑段的段地址由变量所在的段决定。

    当然我们可以添加段超越前缀,改变寄存器指向的段地址。

    这个方式容易和寄存器间接寻址混淆,但我觉得其实就是间接寻址基础上加上个位移量,但是又加上了一些规则。

    mov [BP],AL
    

    注意,[BP]是寄存器相对寻址,因为BP不能用作间接寻址。所以这条指令,是把AL的内容送给某个存储器单元,这个单元的地址一部分是BP内容,一部分为相对位移量,这里为0,即SS:(BP)+0。

    ALmov [BX]+3,AL
    

    目标操作数是寄存器相对寻址,存储器单元地址为BP内容+3.

    这种方式也可以写成

    mov [BX+3],AL
    

    结果相同,汇编后代码相同,只是书写格式不同。

    也可以写成

    mov 3+[BX],AL
    

    当位移量在左边时,加号可以省略,即

    mov 3[BX],A
    

    当位移量是一个变量时

    dat1 DB 12H
    mov dat1[BX],AL
    

    dat1定义在DS段,则dat1[BX]代表的存储器地址为 DS:OFFSET dat1+(BX)

    BP相对寻址的目的

    添加BP进行相对寻址的目的,是为了在不破坏堆栈指针SP的情况下,将堆栈里面的值读取出来

    PUSH AX
    PUSH BX
    PUSH CX
    

    现在将AX内容送给DX,但不能破坏SP内容,怎么做·?

    mov BP,SP
    mov DX,[BP]+4
    

    4.基址、变址寻址

    指的是操作数在存储器某个单元当中,有效地址由两部分组成:第一部分在一个基址寄存器当中——BX,BP两者之一;第二部分在一个变址寄存器中——SI、DI两者之一。两部分之和就是操作数所在存储单元的段内地址。段地址由基址寄存器默认决定。这种寻址方式叫做基址、变址寻址。

    如,用基址、变址寻址方式,将dat1内容送给AL

    dat1 DB 12H
    dat2 DB 34H
    ...
    mov BX,OFFSET dat1
    mov SI,0
    mov AL,[BX][SI]
    

    5.基址、变址相对寻址

    由第三种和第四种结合而来。

    指的是操作数在存储器某个单元当中,有效地址由三部分组成:第一部分在一个基址寄存器当中——BX,BP两者之一;第二部分在一个变址寄存器中——SI、DI两者之一;第三部分是一个8位或16位的DISP相对位移量。三部分之和就是操作数所在存储单元的地址。这种寻址方式叫做基址、变址相对寻址。

    同样的,和第三种一样,如果相对位移量是一个常数,那么对应的逻辑段的段地址由寄存器部分默认决定给出。BX默认在DS段,BP默认在堆栈段SS。

    如果相对位移量是一个变量,会自动取变量的段内偏移地址作为位移量,此时逻辑段的段地址由变量所在的段决定。

    如,用基址、变址相对寻址方式,将dat1内容送给AL

    dat1 DB 12H
    dat2 DB 34H
    ...
    mov BX,0
    mov SI,0
    mov AL,dat1[BX][SI]
    

    4.隐含寻址

    隐含寻址的含义是,指令中并没有写明操作数,但是CPU知道操作数在哪个地方。

    PUSH AL
    

    指令只有单操作数,且是源操作数,没有指明目标操作数在哪里,但是CPU知道怎么做:

    1. SP=(SP)-2

    2. (SS:(SP))=AL

    在8086中,字符串的指令,对于源和目标操作数都是隐含寻址。


    实际当中,我们只需要选择其中之一作为寻址方式即可。

  • 相关阅读:
    【SSH进阶之路】Hibernate映射——一对多关联映射(七)
    深入研究Clang(四) Clang编译器的简单分析
    LLVM每日谈之二十 Everything && Clang driver
    LLVM每日谈之十九 LLVM的第一本系统的书<Getting Started with LLVM Core Libraries>
    session在登录中的使用
    (转)JavaWeb学习总结(十三)——使用Session防止表单重复提交
    网页中自动获取访问用户所在城市的接口插件
    bootstrap新闻模块样式模板
    springmvc的渲染
    springmvc的几点见解
  • 原文地址:https://www.cnblogs.com/ckk-blog/p/14421439.html
Copyright © 2011-2022 走看看