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

1.内存中字的存储

  CPU 中,用16位寄存器来存储一个字。高 8 位存放高位字节,低 8 位存放低位字节。在内存中存储时,由于内存单元是字节单元,则一个字要用两个地址连续的内存单元来存放,这个字的低位字节存放在低地址单元中,高位字节存放在高地址单元中。比如我们从 0 地址开始存放 2000。

  提出了字单元的概念:字单元,即存放一个字型数据(16位)的内存单元,由两个地址连续的内存单元组成。高地址内存单元中存放字型数据的高位字节,低地址内存单元中存放字型数据的低位字节。

  老师在这里提出了小端法和大端法的概念:

  (1)小端法(Little-Endian)就是低位字节排放在内存的低地址端即该值的起始地址,高位字节排放在内存的高地址端。 
  (2)大端法(Big-Endian)就是高位字节排放在内存的低地址端即该值的起始地址,低位字节排放在内存的高地址端。

一般来说我们采用小端法。

2.DS和【address】

CPU要读写一个内存单元的时候,必须先给出这个内存单元的地址。

在8086PC中内存单元由2部分组成:

(1)段地址

(2)偏移地址

8086CPU中有一个DS寄存器地址,通常用来存放数据的段地址。

比如我们要读取10000H的单元内容,可以用如下的程序段进行。

 

mov bx,1000H

mov ds,bx

mov al,[0]

上面3条数据指令将10000H(1000:0)中的数据读到AL中

 mov al,[0]

我们使用mov指令可以完成2种操作:

(1)将数据直接送入寄存器

(2)将一个寄存器中的数据送入到另外一个寄存器。

也可以使用mov指令将一个内存单元中的内容送入一个寄存器中。从哪个内存单元送到哪一个寄存器呢? 所以在指令中必须指明。寄存器用寄存器来指明,内存单元则用内存单元来指明。

 

[...] 表示一个内存单元。[...]中的0表示内存单元的便宜地址。我们知道,只有偏移地址是不能定位一个内存单元的。那么内存单元的段地址是多少呢? 执行指令时,8086CPU会自动取DS中的数据为内存单元的段地址。

 

如何用MOV指令从10000H中读取数据呢? 10000H用段地址和偏移地址表示为1000:0. 我们可以先讲1000H放入DS中。然后mov al,[0].就完成了传送。

mov 指令中[]表示操作的对象是一个内存单元。 [0]表示操作的是一个内存单元的偏移地址是0。它的段地址默认保存是放在ds中。执行指令时,CPU会自动从DS中取出。

 

如何把一个数据送入寄存器?

ds是一个短寄存器,8086CPU不支持将数据直接送入到短寄存器的操作。

那么如何将数据送入进去呢?

我可以在事前用一般的寄存器就好了。如bx,再将bx中的内容送入ds。

 

mov bx,1000H

mov ds,bx

mov al,[0]

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

 

mov bx,1000H

mov ds,bx

mov [0],al 则是将al中的数据送入内存单元10000H中。

 

mov 段寄存器, 寄存器      正确

mov 寄存器, 段寄存器      正确

3.字的传送

  前面我们用mov指令在寄存器和内存之间进行字型数据的传送。因为8086CPU是16位结构,有16根数据线,所以,可以一次性传送16位的数据,也就是说可以一次性传送一个字。只要在mov指令中给出16位的寄存器就可以进行16位的数据传送了。

4 mov,add,sub指令

这三种指令都带有两个操作对象,有一下几种操作类型:

mov:寄存器,数据

mov:寄存器,寄存器

mov:寄存器,内存单元

mov:段寄存器,内存单元

mov:内存单元,寄存器

mov:内存单元,段寄存器

mov:段寄存器,寄存器

mov:寄存器,段寄存器

 

add:寄存器,数据

add:寄存器,寄存器

add:内存单元,寄存器

add:寄存器,内存单元

 

sub:寄存器,数据

sub:寄存器,寄存器

sub:内存单元,寄存器

sub:寄存器,内存单元

5.数据段

数据段:对于 8086PC 机,在编程时,可以根据需要,将一组内存单元定义为一个段。我们可以将一组长度为 N(N<=64KB)、地址连续、起始地址为 16 的倍数的内存单元当作专门存储数据的内存空间,从而定义一个数据段。比如用 123BH~123B9H 这段内存空间来存放数据,我们就可以认为,123B0H~123B9H 这段内存是一个数据段,它的段地址为 123BH,长度为10个字节。

6.栈

 

栈的特性: 后进先出

 

两个概念: 栈底、栈顶

 

两个操作: 入栈、出栈

 

栈段:对于 8086PC 机,在编程时,可以根据需要,将一组内存单元定义为一个段。我们可以将长度为 N(N<=64KB)的一组地址连续、起始地址为 16 的倍数的内存单元,当作栈空间来用,从而定义了一个栈段。

 

 

 

栈的大小是靠我们自己决定的,如何确定这段内存为栈,就需要两个寄存器,段寄存器ss和存放偏移地址的寄存器sp,比如我们决定10000-1000f为寄存器那么ss:sp一开始应该为 1000:0010执行栈有两个指令push,pop,push是入栈执行过程是先sp+2之后在把数据放进去,pop指令是先出栈,先将指令放进栈接着再sp-2。

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

 

 

注意:以下两种情形会发生「栈顶超界」问题:

 

 当栈满的时候,再使用push指令入栈;

 

 当栈空的时候,再使用pop指令出栈;

栈顶超界是危险的,因为我们既然将一段空间安排为栈,那么在栈空间之外的空间里很可能存放了具有其他用途的数据、代码等,这些数据、代码可能是我们自己程序中的,也可能是别的程序中的。但是由于我们在入栈出栈时的不小心,而将这些数据、代码意外地改写,将会引发一连串的错误。


7.段的综述

(1) 段是一个逻辑上的概念。

编程时,可根据需要指定一段内存区用作数据段、代码段或是栈段。

(2) 用作数据段时,要把段地址→DS

     用作栈段时,要把段地址→SS,栈顶偏移地址 → SP

 用作代码段时,段地址→CS,要取的指令偏移地址→IP。但CS和IP的值不能使用mov改变。

(3)  一段内存可以同时用作代码段、数据段、栈段。

     由编程时灵活确定,无论我们怎么安排,CPU将内存中的某段内容当做代码,是因CS:IP指向了那里;CPU将某段内存当做栈,是因为SS:SP指向了那里。

 

posted @ 2018-11-13 17:11  Mr_Gao1  阅读(509)  评论(0)    收藏  举报