mov、add、sub指令

mov 指令可以有以下几种形式:

  1. mov 寄存器,数据 比如:mov ax,8
  2. mov 寄存器,寄存器 比如:mov ax,bx
  3. mov 寄存器,内存单元 比如:mov ax,[0]
  4. mov 内存单元,寄存器 比如:mov [0],ax
  5. mov 段寄存器,寄存器 比如:mov ds,ax

add 和 sub 指令同 mov 一样,都有两个操作对象。它们有一下几种形式:

add 寄存器,数据                        比如:add ax,8
add 寄存器,寄存器                     比如:add ax,bx
add 寄存器,内存单元              比如:add ax,[0]
add 内存单元,寄存器                比如:add [0],ax
sub 寄存器,数据                        比如:sub ax,9
sub 寄存器,寄存器                     比如:sub ax,bx
sub 寄存器,内存单元                比如:sub ax,[0]
sub 内存单元,寄存器                比如:sub [0],ax

延伸出来的方式

  1. mov 寄存器,段寄存器

    mov ax,ds
    
  2. mov 内存单元,段寄存器

    mov ax,1000H
    mov ds,ax
    mov [0],cs
    
  3. mov 段寄存器,内存单元

    mov ax,1000H
    mov ds,ax
    mov ds,[0]
    

    段寄存器

    CS: 代码段寄存器
    IP:代码段偏移
    DS:数据段寄存器
    SS:栈顶段寄存器
    SP:栈顶段偏移地址

    任意时刻,SS:SP 指向栈顶元素
    push ax的执行,由两步完成。

  4. SP = SP - 2,SS:SP 指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶;

  5. 将ax中的内容送入 SS:SP 指向的内存单元处,SS:SP 此时指向新栈顶。

8086 CPU 对 push 指定的执行过程:
image.png

栈越界

8086 CPU并没有提供是否越界的寄存器,所有我们在编程的时候要自己操作栈顶越界的问题,要根据可能用到的最大栈空间来安排栈的大小,防止入栈出栈的数据太多而导致超界。

pop和push

栈的操作都是以字为单位,即2个字节、16位

#将一个寄存器中的数据入栈
push 寄存器
#出栈,用一个寄存器接收出栈的数据
pop 寄存器

#段寄存器也可以
push / pop 段寄存器

#内存单元
push / pop 内存单元
#比如
mov ax,1000H
mov ds,ax        ;内存单元的段地址放在ds中
push [0]        ;将1000:0 处的字压入栈中
pop [2]            ;出栈,出栈的数据送入 1000:2 处

总结

  1. 8086 CPU提供了栈操作机制,方案如下,在SS、SP存放栈顶的段地址和偏移地址;提供入栈和出栈指令,他们根据SS:SP 指示的地址,按照栈的方式访问内存单元
  2. push 指令的执行步骤:a. SP=SP-2;b. 向SS:SP 指向的字单元送入数据
  3. pop指定的执行步骤:a. 从SS:SP 指向的字单元读取数据;b. SP=SP+2
  4. 任意时刻,SS:SP 指向栈顶元素
  5. 8086CPU只记录栈顶,栈空间大小需要自己管理
  6. 栈特点:FILO,先进后出
  7. push、pop 实质上是一种内存传送指令,注意灵活使用

    实验二

    在2000:0 f 内存中,存放了CS,IP,标志寄存器

    问题:add ds,ax正确吗?

    错误,段寄存器不可在算术指令中。