03.寄存器(内存访问)

寄存器(内存访问)

前言

上一节我们从CPU如何执行指令的角度讲解了8086CPU的逻辑结构,形成物理地址的方法,相关的寄存器,以及一些指令。这一节,我们从访问内存的角度继续学习几个寄存器

内存中字的存储

计算机内部的内存单元是字节单元,即 byte 单元。那我们的 字 是如何存储的呢?字 由两个 字节 组成,其中存储在低地址的称之为 低地址单元,存储在高地址的称之为 高地址单元。例如:0X8005H 中的 0X05H 为低地址单元,0X80H 为高地址单元。我们将字这种这种新的存储单元称之为 字单元。将起始地址为 N 的字单元称之为 N地址字单元

DS 和 [address]

CPU 要读取一个内存单元时,必须要给出内存单元的物理地址,而物理地址又由段基址+偏移地址组成.8086CPU使用DS 寄存器来存储要访问的内存单元的段地址。
那我们要如何使用呢?
前面我们提到的 mov 传送指令可以有两种传送:将 数据 直接送入 寄存器;将 寄存器里的数据 送入 另一个寄存器 。现在又有一种新的使用方法:
将某个内存单元的数据存入寄存器:mov ax, [0]
其中 [...] 中的值表示 偏移地址,而段地址里的值存在 DS 寄存器中, 段寄存器 不支持 mov ds 0020H 的指令,但可以使用 mov ds ax 将一个寄存器的数据传送到另一个寄存器中

字的传送

8086CPU 是16位的架构,可以一次性传送16位的数据,也就是一次性可以传送一个字。
因此,只需要在 mov 使用时指定是 16位的寄存器就行了。例如:

  • mov ax, 0001H
  • mov [0], bx
  • mov cx, [0]

mov add sub 指令

mov add sub 这三条指令,它们都带有两个操作数
mov 指令 可以有以下几种形式:

  • mov 寄存器, 数据
  • mov 寄存器, 寄存器
  • mov 内存单元, 寄存器 反之可行
  • mov 段寄存器, 寄存器 反之可行

总之,要遵循一个规律,两个操作数至少有一个可以指定大小
add sub 与 mov 类似,但不能操作段寄存器

数据段

前面讲过,在编程时可以将一段连续的内存单元分为 ,存放代码的地方我们称之为 代码段 ,存放数据的地方称之为 数据段
那么如何访问数据段中的数据呢?
我们可以使用上面提到的 DS 和 [address]

学过数据结构的都知道,栈是一种后进先出(LIFO)的数据结构。有出栈和入栈两种操作。

CPU提供的栈机制

8086CPU 提供相关的指令来以栈的形式访问内存空间,这意味着,在基于 8086CPU 编程时,可以将一段内存当作栈使用,并提供了出栈和入栈的指令,最基本的两个指令是 PUSH(入栈)和 POP(出栈)

  • push ax --> 将ax中的数据送入栈中
  • pop ax --> 将栈顶的取出送入 ax 中
    那么存在以下几个问题?
  • 我们如何知道哪一段内存会被当作栈使用
  • 我们如何知道栈顶位置的内存地址

第一个问题是我们程序员来规定把那一块空间当作栈空间
8086CPU 提供了两个寄存器供我们操作栈,段寄存器 SS 和 寄存器 SP,栈顶的段地址存放在 SS 中,栈顶的偏移地址存放在 SP 中,SS:SP 和 CS:IP 采用的一样的计算方式

下面我们来分析以下push 和 pop 两个指令工作时的具体过程

push ax

  1. sp = sp - 2
  2. 将寄存器数据存入 SS:SP 中

pop ax

  1. 先将栈顶SS:SP中的数据存入寄存器ax中
  2. sp = sp+2

从图中我们可以看出 1000CH ~ 1000F为 栈空间,当栈为空时 栈顶指针指向 1000EH + 2(10010H)处,第一个元素存入 1000EH 处;栈顶 从 高地址 向低地址增长

栈顶超界机制

我们规定一个栈可以存放8个word,栈顶超界有两种情况:

  1. 当我们存满8个元素时,继续 push 就会将不属于栈的数据覆盖
  2. 当我们 pop 已经超界,然后又 push,就会将不属于栈的数据覆盖

我们应该如何规避这种情况呢?很遗憾,8086 CPU 并没有提供相关的机制去规避,这需要我们程序员自己在编写程序的过程中,自己去避免这种情况的发生

pop 和 push 指令

  • push 寄存器
  • push 段寄存器
  • push 内存单元

pop 指令与 push 指令类似

栈段

和 代码段 数据段 类似,都是为了方便我们管理我们的程序

段的综述

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

  • 我们可以用一个段来存放数据,称为 数据段
  • 我们可以用一个段来存放代码,称为 代码段
  • 我们可以用一个段当作栈,称为 栈段

我们可以这样安排,但想要CPU按照我们的安排来访问这些段

  • 对于数据段,我们需要把段地址存入 DS 中,[address] 代表偏移地址
  • 对于代码段,把段地址放入 CS 中,IP 地址指向我们第一条指令
  • 对于栈段,把段地址放入 SS 中,栈顶单元的偏移地址放入 SP 中

可见,不管我们怎么安排,CPU 将内存中的某段内容当作代码,是因 CS:IP 指向了那里,CPU 将某段内存当作栈,是因为 SS:SP 指向了那里,我们一定要清楚,什么是我们的安排,以及如何让 CPU 按照我们的安排工作

参考

<<汇编语言第四版>>-王爽

posted @ 2023-07-31 09:10  异世界穿越中!.!  阅读(30)  评论(0)    收藏  举报