汇编语言学习——寄存器

通用寄存器

  • 在进行数据传送或运算时,需注意指令的两个操作对象位数应当一致,如mov ax, bx,不能将al mov到ax中。

物理地址

  • 8086CPU有20位地址总线,可以传送20位的地址,到达1MB寻址能力。8086又是16位结构,在内部一次性处理、传输、暂存的地址为16位。
  • 8086CPU采用2个16位地址合成的方法形成一个20位的物理地址。物理地址=段地址*16 + 偏移地址

段地址

  • 段地址*16必然是16的倍数,所以一个段的起始地址也一定是16的倍数
  • 偏移地址为16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB。

段寄存器——CS和IP

  • 8086CPU有4个段寄存器,其中CS用来存放指令的段地址。
  • 任意时刻,CS:IP执行的内容当做指令来执行
  • 通过jmp指令修改CS:IP,可以使用jmp 段地址:偏移地址同时修改CS和IP的内容,若仅修改IP的内容,则可以通过jmp 某一合法寄存器完成,如jmp ax会将ax中的值修改IP。

DS和[address]

mov指令可以完成两种传送:

  1. 将数据直接送入寄存器
  2. 将一个寄存器中的内容送入另一个寄存器
  3. 也可以将一个内存单元中的内容送入一个寄存器中
  4. [...]表示一个内存单元,其中的内容表示内存单元的偏移地址
  5. 8086CPU自动取DS中的数据作为内存单元的段地址
  6. 8086CPU不支持将数据直接送入段寄存器(硬件设计原因)
1
2
3
mov bx, 1000H
mov ds, bx
mov al, [0]

上面的指令将内存单元10000H(1000:0)中的数据读到al中。

字在内存中的存储*

  • 字在内存中存放需要2个连续地址的内存单元存放,字的低位字节在低地址单元中,高位字节存放在高位地址单元中。
  • mov,add,sub是具有2个操作对象的指令,jmp是具有一个操作对象的指令。

CPU栈的机制

  • 如今的CPU都有栈的设计
  • 8086CPU的入栈和出栈操作都是以字为单位进行的,如:push ax ; 将ax中的内容放入当前栈顶单元是上方,pop bx ; 从栈顶单元取出数据送入bx
  • 任意时刻SS:SP指向栈顶元素
  • 一个栈段的最大容量为64KB(栈通过SP寻址,所以栈顶的变化范围是0~FFFFH,最大能指向64KB)

push ax操作分析

  1. SP=SP-2,SS:SP只想当前栈顶前面的单元,以当前栈顶前面的单元为心的栈顶
  2. 将ax中的内容送入SS:SP指向的内存单元,SS:SP此时指向新栈顶

如果将10000H~1000FH这段空间当做栈,初始状态栈是空的,此时SS=1000H,那么SP=?

SP地址分析

栈顶越界问题

编程时需要自己操心栈顶超界问题,需要根据可能使用到的最大的栈空间,来安排栈的大小,方式数据过大越界。

push,pop指令

push和pop的操作对象可以是:寄存器,段寄存器,内存单元。如:

1
2
3
push ax
push ds
pop [2]

段的综述

  • 我们可以用一个段存放数据,将它定义为“数据段”,将它的段地址放在DS中,用mov,add,sub访问内存单元指令时,CPU就将我们定义在数据段中的内容当做数据来访问。
  • 我们可以用一个段存放代码,将它定义为“代码段”,将它的段地址放在CS中,将段中的第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义在代码段中的指令。
  • 我们可以用一个段当做栈,将它定义为“栈段”,将栈顶单元的偏移地址放在SP中,这样CPU在需要进行栈操作的时候,比如执行push,pop指令等,就将我们定义的栈段当做栈空间来用。

附,寄存器清零操作

比如将ax清零。可以使用sub ax, ax(机器码只占2个字节)或mov ax, 0(机器码占3个字节)