1、内存中字的存储

  低位对应低地址位,高位对应高地址位;

wKiom1gVMnLiUN2MAAAF_I1WErA893.png-wh_50

结论:任何两个地址连续的内存单元,N和N+1号单元,可以将他们看作2个内存单元,也可以看成一个地址为N的字单元的高位字节单元和低位字节单元。


2、DS和地址

  在8086PC中,内存地址由段地址和偏移地址组成;

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

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

  8086CPU不支持将数据直接送入段寄存器的操作,DS是一个段寄存器(硬件设计的问题)

  所以mov ds,1000H是非法的。

  数据怎样给段寄存器:数据---->通用寄存器---->段寄存器

  字的传送:

  因为8086CPU是16位的结构,有16根数据线,所以,可以一次性传送16位的数据,可以理解为一次传送一个字。


3、mov、add、sub指令

  (1)、mov指令的几种形式

  mov 寄存器, 数据   :mov ax, 6  

  mov 寄存器, 寄存器   :mov bx, ax

  mov 寄存器, 内存单元   :mov ax, [0](偏移地址)

  mov 内存单元, 寄存器   :mov [0], ax  //将ax寄存器中的值,放到内存单元段地址是ds,在结合我们给出的偏移地址[0],找到对应的内存,最后把这个值放进去;

  mov 段寄存器, 寄存器   :mov ds, ax

例如:

wKiom1gVP8DQalEUAAAll_T4wOw304.png-wh_50

验证一下有没有mov 寄存器,段寄存器

wKioL1gVQOrCHitbAAAths7esus578.png-wh_50

  (2)、add和sub指令同mov一样,都有2个操作对象,进行对数值的加/减运算;


4、数据段

  在8086PC机中,我们可以根据需要将一组内存单元定义为一个段(可以是代码段、数据段等)。

  可以自己将一组长度为N(N<64K)、地址连续、起始地址为16的倍数的单元用来存储数据的内存空间,从而定义了一个数据段。

  怎么数据段中的数据?

  :将一段内存当作数据段,是我们在编程时的一种安排,用ds存放数据段的段地址,在根据情况写出偏移地址就可以访问了;


5、栈

  (1)、栈:具有特殊的访问方式的存储空间,特殊性:先进后出;

  栈的2个基本操作:入栈(PUSH)和出栈(POP);8086CPU的入栈/出栈都是以字为单位进行的;

  CPU一般都提供了栈这个机制;8086CPU提供相关的指令来以栈的方式访问内存空间。

  (2)、push ax :将寄存器ax中的数据送入栈中;

  push ax :从栈顶取出数据送入ax中。

  (3)、CPU如何知道一段内存空间被当做栈使用?

  :寄存器CS和IP中存放着当前指令的段地址和偏移地址;

  :8086CPU中,有2个寄存器,SS(段寄存器):存放栈顶的段地址;SP(寄存器):存放栈顶的偏移地址

  :任意时刻,SS和SP指向栈顶元素(在进行push/pop的过程中,SS:SP将会不断的变化,始终指向栈顶元素)

  (4)、换个角度来看看SS:SP

  任意时刻,SS:SP指向栈顶元素,当栈为空的时候,栈中没有元素,也就不存在栈顶元素,所以此时,SS:SP只能指向栈的最底部单元下面的单元,该单元的偏移地址为栈最底部的字单元的偏移地址+2,栈最底部字单元的地址为1000:000E,所以栈空时,SP=0010H。

 

6、栈顶越界

  SS和SP只记录了栈顶的地址,栈顶越界是危险的。

  :因为在栈之外的空间里可能存放了具有其他用途的数据、代码等,这些数据、代码可能是我们自己程序中的,也可能是别的程序中的。

  CPU只知道要执行的指令在何处,但是不知道要执行的指令有多少。

  8086CPU的工作机理:当前栈顶在何处,当前要执行的指令是哪一条;

  结论:在编程时自己小心对越界的操作问题。


7、push和pop

  (1)、指令的格式:

  i>、push 寄存器   pop 寄存器

  ii>、push 内存单元 :将一个内存单元的字入栈; push [0]

  pop 内存单元 :用一个内存单元接受出栈的数据; pop [2]

  (2)、push、pop等栈操作指令,修改的只是SP,可以得知:栈顶的变化范围最大为:0-FFFFH。


8、栈的综述

  (1)、8086CPU提供栈操作机制,方案:SS、SP中分别存放栈顶的段地址和偏移地址;

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

  (3)、8086CPU只记录栈顶,栈空间的大小我们要自己管理;

  (4)、寄存器出栈顺序和入栈顺序是相反的。


9、段

  将一段内存定义为一个段,有段地址,有偏移地址访问段内的单元,这些都是我们自己安排的。CPU将内存看成一个逻辑单元,我们看的是一个一个的段;

  我们可以用一个段来存放数据,将其定义为"数据段";

  我们可以用一个段来存放代码,将其定义为"代码段";

  我们可以用一个段当作栈,将其定义为"栈段";

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

  (1)、对于数据段,将它的段地址放在DS中,用mov、add、sub访问内存单元指令时,CPU就将我们定义的数据段中的内容当做数据段来访问;

  (2)、对于代码段,将它的段地址放在CS中,将段中的第一条偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令;

  (3)、对于栈段,将它的段地址放在SS中,栈顶单元的偏移地址放到SP中,CPU在执行push、pop等指令时,就将我们定义的栈段当做栈空间来用;

  可以得出:不管我们怎么安排,CPU将内存中的某段内存当做代码,是因为CS:IP指向了那里;CPU将某段内存当做栈,是因为SS:IP指向了那里。

 

10、总结

  一段内存,可以是代码、数据、栈中的任意空间,也可以什么都不是,关键在于CPU中寄存器的设置,即:CS、IP、SS、SP、DS的指向。