编译原理学习笔记(第三章 寄存器(内存访问))

寄存器(内存访问)

之前从从访问内存的角度再来学几个重要的寄存器。

3.1、内存中字的储存

CPU中,用16位寄存器来储存一个字(两个字节),但是内存单元是字节单元(一个单元存放一个字节),所以一个字要用两个连续的内存单元来存放,低位字节存放低地址单元中,高位字节存放在高地址单元中。

所以我们提出字单元的概念:**字单元,即存放一个字型数据(16位)的内存单元,由两个地址连续的内存单元组成。**一般将起始地址为N的单元称为N地址字单元。

3.2 DS和[address]

CPU要读取一个内存单元的时候,必须先给出这个内存单元的地址。比如要读取10000H单元的内容,可以用如下的程序段进行:

mov bx, 1000H
mov ds, bx
mov al, [0]

上面的三条指令将 10000H(1000:0)中的数据读到 al 中。

由于8086CPU不支持将内存数据直接读入ds(段寄存器),所以需要先将内存数据先读入bx(通用寄存器),然后再将数据在寄存器间转移。

“ mov al, [0] ”中 “[ ]” 表示一个内存单元, “[ ]” 中的 0 表示内存单位的偏移地址,而内存的段地址是 8086CPU 从 ds 寄存器中自动读取的,所以在把数据移入寄存器中之前,需要先行把 1000H 送入ds。

3.3、字的传送

因为 8086CPU 是 16 位结构,有 16 根数据线,所以可以一次传送一个字。只要在 mov 指令中给出 16 位的寄存器就可以进行 16 位数据的传送了。

3.4、mov、add、sub指令

mov用法汇总:

指令格式 示例代码
mov 寄存器,数据 mov ax,8
mov 寄存器,寄存器 mov ax,bx
mov 寄存器,内存单元 mov ax,[8]
mov 内存单元,寄存器 mov [8],ax
mov 内存单元,段寄存器 mov ax,1000H; mov ds,ax;mov [0],cs
mov 段寄存器,内存单元 mov ax,1000H; mov ds,ax;mov ds,[0]
mov 段寄存器,寄存器 mov ds,ax
mov 寄存器,段寄存器 mov ax,ds

注意,当使用 ax 寄存器与内存空间之间进行操作时,内存偏移的地址为 2,因为 ax 为十六位寄存器,每次传输数据时会传输一个字大小的

add用法汇总:

指令格式 示例代码
add 寄存器,数据 add ax,8
add 寄存器,寄存器 add ax,bx
add 寄存器,内存单元 mov ax,[8]
add 内存单元,寄存器 mov [8],ax

add 不能操作段寄存器!因为段寄存器用于存放段地址,不能作为操作数(硬件层面没有实现)。

sub 同理。

3.5、数据段

对于 8086PC,可以根据需要,把一组内存单元定义为一个段。如果将**一组长度为N(N <= 64KB)、地址连续、起始地址为 16 的倍数的内存单元当作专门储存数据的内存空间,**这段内存空间被称为 “数据段”

在具体操作时,用 ds 存放数据段的段地址,再根据需要用相关指令访问。

3.6、栈

操作规则:LIFO(Last In First Out)

从程序化的角度说,有一个标记一直指示着栈顶的元素。

3.7、CPU 提供的栈机制

8086CPU 提供相关的指令来以栈的方式访问内存空间,就是说,可以把一段内存当作栈来使用。

相关指令:

  • push ax(把 ax 中的数据压入栈中)
  • pop ax(弹出栈顶数据存入 ax)

以上指令以字为单位进行

那么,CPU是如何确定哪段内存被作为栈来使用呢?

任意时刻,SS:SP 指向栈顶元素,push 和 pop 指令执行时,CPU 从 SS 和 SP 中得到栈顶的地址。

3.8、栈顶越界问题

8086CPU 中并没有记录栈的容量的寄存器,它只考虑当前栈顶的位置,所以无论是入栈还是出栈时都有可能使得栈顶越界,使得栈空间以外的数据、代码被覆盖。

3.9、push、pop 指令

除了通用寄存器以外,push 同样可以把段寄存器、内存单元作为操作数。

切记:push 和 pop 的操作规模永远是一个字。

3.10、栈段

对于 8086PC,可以根据需要,把一组内存单元定义为一个段。如果将**一组长度为N(N <= 64KB)、地址连续、起始地址为 16 的倍数的内存单元当作专门栈空间的内存空间,**这段内存空间被称为 “栈段”

前提:将 SS:SP 指向我们定义的栈段。

你可能感兴趣的:(学习笔记,栈,操作系统,cpu)