第三章 寄存器(内存访问)
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指向了那里。

浙公网安备 33010602011771号