course83_lab2_8086的寻址方式

8086 cpu中总的寄存器

8086 CPU 中寄存器总共为 14 个,且均为 16 位 。

即 AX,BX,CX,DX,SP,BP,

SI,DI,IP,FLAG,CS,DS,SS,ES 共 14 个。

而这 14 个寄存器按照一定方式又分为了

  • 通用寄存器,
  • 控制寄存器和
  • 段寄存器。

1. 通用寄存器

1.1通用寄存器中的数据寄存器

AX,BX,CX,DX 称作为数据寄存器:

  • AX (Accumulator):累加寄存器,也称之为累加器;

  • BX (Base):基地址寄存器;

  • CX (Count):计数器寄存器;

  • DX (Data):数据寄存器;

可以分为两个独立的 8 位的 AH(BH, CH, DH) 和 AL(BL, CL, DL) 寄存器.

1.2 通用寄存器中的指针寄存器

SP 和 BP 又称作为指针寄存器:

  • SP (Stack Pointer):堆栈指针寄存器;

  • BP (Base Pointer):基指针寄存器;

1.3 通用寄存器中的变址寄存器

SI 和 DI 又称作为变址寄存器:

SI (Source Index):源变址寄存器;

DI (Destination Index):目的变址寄存器;

2. 控制寄存器

控制寄存器:

  • IP (Instruction Pointer):指令指针寄存器;

  • FLAG:标志寄存器;

3. 段寄存器

我们可以将一段内存定义为一个段, 用一个段地址指示段, 用偏移地址访问段内的单元,
这完全是我们自己的安排。

  • 可以用一个段存放数据, 将它定义为“数据段”;
  • 可以用一个段存放代码, 将它定义为“代码段”;
  • 可以用一个段当做栈, 将它定义为为“栈段”

3.1 DS (Data Segment):数据段寄存器; DS: []

对于数据段, 将它的段地址放在DS中, 用 mov, add, sub 等访问内存单元的指令时, CPU 就将我们定义的数据段中的内容当做数据来访问;

使用[xx], 表示段地址是在 DS 中,其中的[] 表示偏移地址,

实际的物理地址 = 段地址 × 16 + 偏移地址;

具体的实现过程便是将, 段地址左移一位, 加上偏移地址。

3.2 CS (Code Segment):代码段寄存器; CS:IP

对于代码段, 将它的段地址放在CS中, 将段中第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令。

所以CPU中的内存中的某段内容当做代码, 是因为CS:IP 指向那里,

3.3 SS (Stack Segment):堆栈段寄存器; SS:SP

对于栈段, 将它的段地址放在SS中, 将栈顶单元的偏移地址放在 SP中, 这样CPU在进行栈操作的时候, 比如执行push, pop 指令等, 就将我们定义的栈段当做栈空间来使用;

故,CPU将某段内存当做栈, 是因为SS:SP 指向了那里;

注意: debug de T 命令在执行修改寄存器 SS的指令时, 下一条指令也紧跟着被执行。

3.4 ES (Extra Segment):附加段寄存器;

4. 操作数寻址

汇编指令由 操作码字段操作数字段 构成。

对于双操作指令,第一个操作数称为目的操作数,表示操作后的结果;

第二个操作数称为源操作数,表示来源操作数。
两者以逗号分隔。如:

在这里插入图片描述

  • 寻址方式,即指令中提供操作数或操作数地址的方式。通俗地说就是寻找操作数地址的方法。

  • 寻址方式的数量: 代表了微机系统对存储器管理能力的强弱,合理地使用寻址方式可以扩大访存空间,缩短指令长度,满足各种程序设计需要。

数据有关的寻址方式划分为三类

  • 立即寻址方式,
  • 寄存器寻址方式,
  • 存储器寻址方式。

掌握下列七种与数据有关的寻址方式。其中后五种属于存储器寻址方式。

  • 立即寻址方式(Immediate addressing)
  • 寄存器寻址方式(Register addressing)
  • 直接寻址方式(Direct addressing)
  • 寄存器间接寻址方式(Register indirect addressing)
  • 寄存器相对寻址方式(Register relative addressing)
  • 基址变址寻址方式(Based indexed addressing)
  • 相对基址变址寻址方式(Relative based indexed addressing)

我们看到,常用的寻址方式有 7 种之多,到底选择哪一种为好呢?

选择寻址方式有两条原则:第一实用,第二有效。

最终都应达到运行速度快、指令代码短的高效率目标程序的目的。

立即寻址和寄存器寻址无论从指令长度和指令执行时间都比存储器寻址要好,但是也要根据具体情况选用。

4.1 立即寻址

立即寻址方式(Immediate addressing):

所要找的操作数直接写在指令中,这种操作数叫立即数。

在 8086、80286 中立即数是 8 位或 16 位的,
在 80386 以上可以是 32 位的立即数
立即寻址方式用来表示常数。

MOV AX, 1234H ; 给AX寄存器赋值为1234H

在这里插入图片描述

在 DEBUG 下数据都是十六进制表示的,因此不需要用 H 标注,同时要把十进制变为十六进制才行。

在 DEBUG 下执行:

-A
MOV AX,3060
MOV AL,5
MOV BL,FF
MOV BX,A46D 
MOV CX,17

接着用 T 命令单步执行,观察各寄存器的值。

注意: 执行 T 命令之前,指令指针寄存器 IP 的值要用R IP 修改成第一条指令的偏移地址,这样 T 命令才能从第一条指令开始执行。

4.2 寄存器寻址

在寄存器寻址方式中,操作数在寄存器中,在指令中指定寄存器名即可。

在这里插入图片描述
在 DEBUG 下执行:

-A
MOV AX,0
MOV BX,1234
MOV AX,BX
MOV CL,AH
MOV AX,4650
  • 接着用 T 命令单步执行,观察各寄存器的值。

  • 要注意指令指针 IP 的值是否指向了要执行的指令
    ( 这一步骤的作用是将, ip 指针,指向了第一个指令的地址)。
    在这里插入图片描述

MOV DX, AX ;将AX中的值赋给DX 

直接使用寄存器中的值作为操作数, 速度较快.

4.3 直接寻址

  • 操作数存放在内存中。

  • 操作数的偏移地址(也称为有效地址 EA)直接写在指令中。

注意写法

  • mov al, [address] 的意思将DS:address 中的内存数据赋值到al寄存器中。

  • 8086 不支持直接将数据写入段寄存器,mov ds, 1000H 是错误的。

1)存储器读操作

MOV 指令可以实现 CPU 对存储器的读写。
若传送指令的目的操作数是 CPU 的寄存器,源操作数是存储单元,就完成了对存储器的读操作。

例如:MOV AX,[2000H]
表示该指令表示从数据段的 2000H 单元读出一个字送入 AX。

(2)存储器写操作

如果要实现 CPU 写内存操作,只要把 MOV 指令的目的操作数变为存储单元,源操作数为 CPU 的寄存器即可。

例如:MOV [4000H],AX 将 AX 的值写入数据段的 4000H 单元。

在 DEBUG 下执行:

-A
MOV AX,[2000]
MOV [4000],AX

接着用 T 命令单步执行,观察 AX 寄存器的值;用 D DS:2000D DS:4000 命令观察这两个存储单元的值。


操作数存放在存储器中, 偏移量直接写在操作数中,.

地址为数据段寄存器DS的值* 16 (<<4)然后加上直接给出的偏移量2000H.

MOV BX, [2000H]

4.4 寄存器间接寻址

操作数存放在内存中。

指令形式如:

MOV  AX,[BX]
  • 操作数的 EA 在基址寄存器 BX、BP 或变址寄存器 SI、DI 中,而操作数的段地址在数据段 DS 或堆栈段 SS 中。

  • 如果有效地址由 BX、SI、DI 指出,则默认为对应于数据段,而用 BP 指出则对应于堆栈段。
    ------------------- 举例-------------------
    在这里插入图片描述

思考一下,在 DEBUG 下执行时,如果按照上例给出的数据段地址和 BX 值来执行,如何实现呢?执行后怎样看到 AX=2364H?

解法如下:

-R DS 1500
-E DS:4580  64 23
-D DS:4580
-A
MOV BX,4580
MOV AX,[BX]

接着用 T 命令单步执行,观察 AX 寄存器的值。

注意:指令指针 IP 的值是否指向了要执行的指令?

在这里插入图片描述


操作数存放在存储器中, 16位偏移地址存放在SI, DI, BP, BX四个寄存器之一中.

若使用BX, SI, DI之一作为寄存器, 操作数默认放在DS所决定的数据段中.
即地址为:DS *16 + BX
12

MOV AX, [SI] ; 将DS*16 + SI中的值放入AX中

若使用BP做间接寻址, 操作数默认放在SS决定的堆栈段中.

MOV AX, [BP]  ;将SS*16 + BP中的值放入AX中

可以直接指定使用的段寄存器:

MOV  AX, SS:[SI]  ;将SS*16 + SI中的值放入AX中

4.5 寄存器相对寻址

操作数存放在内存中。

指令形式如:

MOV  AX,[BX+1200H]

操作数的 EA 是一个基址或变址寄存器的内容再加上 8 位或 16 位位移量之和。

也就是说在寄存器间接寻址的基础上,增加一个相对量(位移量)。这个位移量可以是立即数,也可以是符号地址。

在这里插入图片描述

思考一下,如果按照上例给出的参数来执行,在 DEBUG 下执行时如何修改指令呢?

  • 执行后怎样看到 AX=2428H?

提示:符号地址 TOP 直接用 25H 表示。
解法如下:

-R DS 1500
-E DS:7335  28 24
-D DS:7335
-A
MOV SI,7310
MOV AX,25[SI]

接着用 T 命令单步执行,观察 AX 寄存器的值。

注意:执行 T 命令之前,指令指针寄存器 IP 的值要用 R IP 修改成第一条指令的偏移地址。
在这里插入图片描述

----------------------------

操作数存放在存储器中, 使用段寄存器内容* 16 加SI, DI, BP, BX四个寄存器之一的内容再加直接给出的位移量.

若使用BX, SI, DI之一作为寄存器, 操作数默认放在DS所决定的数据段中; 若使用BP做间接寻址, 操作数默认放在SS决定的堆栈段中.

与寄存器间接寻址相比只是增加了直接给出的偏移量:

MOV AX, [SI-2] ; 将 DS*16 + SI - 2中的值放入AX中
MOV AX, [BP+4]  ;将 SS*16 + BP + 4中的值放入AX中
MOV  AX, SS:[SI-8]  ;将 SS*16 + SI - 8中的值放入AX中

4.6 基址变址寻址方式

操作数存放在内存中。

指令形式如:

MOV  AX,[BX+SI]

操作数的 EA 为一个基址寄存器和一个变址寄存器的内容之和。


将段地址寄存器的值*16加上基址寄存器(BX,BP)之一的地址加上变址寄存器(SI, DI)之一的值作为地址.

若使用BX作基址 操作数默认放在DS所决定的数据段中; 若使用BP做基址, 操作数默认放在SS决定的堆栈段中.

MOV AX, [BX][SI] ; 将 DS*16 +BX + SI中的值放入AX中
MOV AX, [BP][DI]  ;将 SS*16 + BP + DI 中的值放入AX中
MOV  AX SS:[Bx][SI]  ;将 SS*16 + BX + SI 中的值放入AX中

4.7 基址变址相对寻址

操作数存放在内存中。

指令形式如:

MOV  AX,[BX+SI+1200H]   

操作数的 EA 为一个基址寄存器加一个变址寄存器再加一个位移量,三者之和。可用于二维表查表和栈处理。

自己做:自定各个寄存器的参数,在 DEBUG 下执行指令后得到 AX=3568H。

在基址变址寻址基础上再加一个直接给出的偏移量:

MOV AX, 1234H[BX][DI] ;将DS * 16 + BX + DI + 1234H中的值放入AX中.

还有几种表示方法与上式等价:

MOV AX, [BX+DI+1234H]
MOV AX, 1234H[BX+DI]
MOV AX, 1234H[BX][DI]

5. 实验

5.1 两数相加

根据题目要求,写出相应的汇编指令:

  1. AX、BX 寄存器分别赋值为 0008H 和 0006H
  2. AX 和 BX 的内容相加,结果在 AX 中
  3. 用寄存器间接寻址将相加的结果保存到 6 号单元,指令如下:
MOV AX,0008H
MOV BX,0006H
ADD AX,BX
MOV [BX],AX
HLT                   ;停机指令

在 DEBUG 下,用 A 命令输入上述四条指令,再用 R 命令显示寄存器的情况:

在这里插入图片描述

用 T 命令单步执行(注意:第一条指令的偏移地址是 0100,IP 寄存器的值也应是 0100);用 D 命令观察结果:

在这里插入图片描述
实验结果分析如下:

  1. 执行两次 T 命令后,AX=0008H, BX=0006H。
  2. 执行加法命令后,AX=000EH;相应的标志位:进位标志 NC,即 CF=0;符号标志 PL,即 SF=0;零标志 NZ,即 ZF=0;溢出标志 NV,即 OF=0;表示运算结果无进位、不溢出、结果不为 0、结果是正数。
  3. [BX] 寄存器间接寻址方式对应的存储单元为 6 号,逻辑地址为 DS:0006,该单元原来的值为 FEEEH。
  4. 执行完 MOV [BX],AX 指令后,DS:0006 单元中的内容变为000EH了(用 D DS: 6 命令查看 DS 段的 6 号和 7 号单元)。

在这里插入图片描述

5.2 两数相减

  1. 实验目的
    通过实验观察和分析在不同的寻址方式下存储单元逻辑地址的表示以及指令的执行结果。
    熟练掌握 DEBUG 的 R 命令、A 命令、T 命令和 D 命令的用法。

  2. 实验内容
    参考示例一和各种寻址方式完成下列实验内容:

(1)两个操作数相减运算,结果放在数据段的 16 号单元
AX、BX 寄存器分别赋值为 0008H 和 0010H;
AX 和 BX 的内容相减(SUB 指令),结果在 AX 中;
用直接寻址方式将相减的结果保存到 16 号单元。

(2)两个操作数相加运算,结果放在附加段的 0020H 号单元
AX 的值为 0034H;
AX 和 65 相加,结果在 AX 中;
用寄存器间接寻址方式(段超越)保存运算结果。

(3)将 AX 寄存器中的 1234H 写入数据段的 2 号单元,读出 3 号单元的 12H 传送给 BL 寄存器(寻址方式自定)

  1. 实验要求
    写出相关命令及操作步骤
    实验内容用截图形式记录实验结果
    写出实验结果分析。

提示:减法的结果以补码形式表示,对应的真值为负数。标志位发生了改变。

实验拓展
根据自己的理解和偏好,设计并完成其他寻址方式的指令。
这些实验对你有何启发?

referenc:
参考1

猜你喜欢

转载自blog.csdn.net/chumingqian/article/details/125014314