【王爽《汇编语言(第4版)》笔记】第3章:寄存器(内存访问)

第3章 寄存器(内存访问)

3.1 内存中字的存储

1、一个字要用两个地址连续的内存单元来存放

2、低位字节存放在低地址单元中,高位字节存放在高地址单元中

3、字单元:存放一个字型数据(16位)的内存单元,由两个地址连续的内存单元组成。高地址内存单元存放字型数据的高位字节低地址内存单元中存放字型数据的低位字节

4、将起始地址为N的字单元称为N地址字单元N号单元存放低位字节,N+1号单元存放高位字节
在这里插入图片描述

3.2 DS和[address]

1、8086CPU中的DS寄存器通常用于存放要访问的数据的段地址。(与CS的区别:CS存放的是指令的段地址

2、将10000H(1000:0)中的数据读取到al中:

mov bx, 1000H
mov ds, bx
mov al, [0] // 将地址为ds:0的内存单元中的内容送入al中

3、用mov指令将一个内存单元中的内容送入一个寄存器中

mov 寄存器名, 内存单元地址

4、"[…]“表示一个内存单元,”[…]"中的数字表示内存单元的偏移地址

5、指令执行时,8086CPU自动取ds中的数据为内存单元的段地址

6、由于8086CPU硬件设计问题,不支持将数据直接送入段寄存器

mov 段寄存器, 数据 // 错误指令

3.3 字的传送

1、8086CPU是16位结构,有16根数据线,所以可以一次性传送16位的数据,即一次可以传送一个字。

2、只要在mov指令中给出16位的寄存器就可以进行16位数据的传送了,例如:

mov bx, 1000H
mov ds, bx
mov ax, [0] // 将1000:0处的字型数据送入ax
mov [0], cx // 将cx中的16位数据送到1000:0处

3、在内存和寄存器之间传送字型数据时,高地址单元和高8位寄存器、低地址单元和低8位寄存器相对应。

3.4 mov、add、sub指令

1、mov指令的几种形式

mov 寄存器, 数据
mov 寄存器, 寄存器
mov 寄存器, 内存单元
mov 内存单元, 寄存器
mov 段寄存器, 寄存器
mov 寄存器, 段寄存器
mov 内存单元, 段寄存器
mov 段寄存器, 内存单元

2、add指令的几种形式

add 寄存器, 数据
add 寄存器, 寄存器
add 寄存器, 内存单元
add 内存单元, 寄存器

3、sub指令的几种形式

sub 寄存器, 数据
sub 寄存器, 寄存器
sub 寄存器, 内存单元
sub 内存单元, 寄存器

3.5 数据段

我们可以根据需要,将一组长度小于64KB、地址连续、起始地址为16的倍数的内存单元定义为一个数据段,用来作为专门存放数据的内存空间。

3.6 栈

1、栈是一种具有特殊的访问方式的存储空间

2、栈的基本操作:

(1)入栈:将一个新的元素放到栈顶;

(2)出栈:从栈顶取出一个元素。

3、栈的操作规则:LIFO(Last In First Out,后进先出)。

3.7 CPU提供的栈机制

3.7.1 CPU栈机制概述

1、现今的CPU都有栈的设计。

2、在基于8086CPU编程的时候,可以将一段内存当作栈来使用

3、8086CPU提供入栈和出栈指令,最基本的是push和pop:

push ax // 表示将寄存器ax的数据送入栈中
pop ax // 表示从栈顶取出数据送入ax

4、8086CPU的入栈和出栈操作都是以字为单位进行的。

5、字型数据用两个单元存放,高地址单元存放高8位,低地址单元存放低8位

3.7.2 段寄存器SS和寄存器SP

Q1:CPU如何知道哪段空间被当作栈来使用?

Q2:CPU如何知道哪个单元是栈顶单元?

1、8086CPU中的段寄存器SS寄存器SP存放的内容:

(1)段寄存器SS:存放栈顶的段地址;(2)寄存器SP:存放偏移地址

2、任意时刻,SS:SP指向栈顶元素。

3、push指令和pop指令执行时,CPU从SS和SP中得到栈顶的地址。

4、初始化栈顶的常用代码:

mov ax, 1000H 
mov ss, ax // 不能直接mov 段寄存器, 数据
mov sp, 0020H
3.7.3 push指令的执行过程

1、push ax的执行,由以下两步完成:

(1)SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;

(2)将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。

2、入栈时,栈顶从高地址向低地址方向增长。
在这里插入图片描述

3.7.4 栈空状态下的栈顶

任意时刻,SS:SP指向栈顶元素,当栈为空的时候,栈中没有元素,不存在栈顶元素,所以:

1、SS:SP只能指向栈的最底部单元下面的单元

2、该单元的偏移地址为栈最底部字单元的偏移地址+2

3、如果将10000H~1000FH这段空间当作栈,初始状态栈是空的,此时,SS=1000H,则SP=0010H,如图所示:
在这里插入图片描述

3.7.5 pop指令的执行过程

1、pop ax的执行,由以下两步完成:

(1)将SS:SP指向的内存单元处的数据送入ax中

(2)SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。

2、出栈的数据并不会被删除,需要通过指令在其中写入新的数据时才能覆盖。
在这里插入图片描述

3.8 栈顶超界的问题

3.8.1 栈顶超界的情况与后果

1、以下两种情况会发生栈顶超界

(1)当栈满的时候,再使用push指令入栈;
在这里插入图片描述
(2)当栈空的时候,再使用pop指令出栈。
在这里插入图片描述
2、栈顶超界的后果:栈顶超界是危险的,可能损坏在栈空间之外的空间中存放的数据、代码等,并引发错误。

3.8.2 关于8086CPU栈顶超界的问题

1、8086CPU不保证不会发生栈顶超界。

2、8086CPU只知道栈顶在何处(由SS:SP指示),而不知道栈空间的大小

3、8086CPU的工作机理:只考虑当前情况,即

(1)当前的栈顶在何处;(2)当前要执行的指令是哪一条。

4、编程时需要自己注意栈顶超界问题,根据可能用到的最大栈空间,来安排栈的大小,执行入栈出栈时需注意。

3.9 push、pop指令

3.9.1 push、pop指令的格式

1、push、pop指令是可以在寄存器和内存之间传送数据的。

2、栈空间内存空间的一部分,是一段可以以一种特殊方式进行访问的内存空间。

3、push、pop指令格式:

push 寄存器 // 将一个寄存器中的数据入栈
pop 寄存器 // 出栈,用一个寄存器接收出栈的数据
push 段寄存器 // 将一个段寄存器的数据入栈
pop 段寄存器 // 出栈,用一个段寄存器接收出栈的数据
push 内存单元 // 将一个内存字单元处的字入栈(注意:栈操作都是以字为单位)
pop 内存单元 // 出栈,用一个内存字单元接收出栈的数据
// 可以只给出内存单元的偏移地址,段地址从ds获得
3.9.2 push、pop指令的注意事项

1、用栈暂存以后需要恢复的寄存器中的内容时,出栈顺序应与入栈顺序相反,因为后进先出。

2、push、pop指令是内存传送指令,可以在寄存器和内存之间传送数据。

3、push、pop指令与mov指令的区别:

(1)push和pop指令访问的内存单元的地址由SS:SP指出,而不是在指令中给出;

(2)push和pop指令会改变SP中的内容

(3)CPU执行mov指令只有一步,即传送,而push和pop指令的执行过程有两步。

4、push和pop只修改SP,不修改SS,栈顶变化范围最大为0~FFFFH。

5、栈顶可以出现环绕的情况,见书P69问题3.12。

3.10 栈段

1、栈段的概念:可以将长度小于64KB的一组地址连续、起始地址为16的倍数的内存单元,当作栈空间来用,从而定义了一个栈段

2、将一段内存当作栈段是编程时的人为安排,而不是CPU的安排。

3、使push、pop指令访问我们定义的栈段,就需要将SS:SP指向我们定义的栈段

数据段、代码段、栈段小结

1、内存本身并不分段,将内存分段是我们自己的安排。

2、让CPU访问我们安排的段的方法:

(1)数据段:段地址存放在DS中;

(2)代码段:段地址存放在CS中,段中第一条指令的偏移地址存放在IP中。

(3)栈段:段地址存放在SS中,栈顶单元的偏移地址存放在SP中。

3、CPU将内存中的某段内容当作代码,是因为CS:IP指向那里;将某段内容当作栈,是因为SS:SP指向那里。

4、一段内存,可以既是代码的存储空间,又是数据的存储空间,还可以是栈空间,也可以什么也不是。这些取决于CPU中寄存器的设置,即CS、IP,SS、SP,DS的指向

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值