汇编语言学习——寄存器
通用寄存器
- 在进行数据传送或运算时,需注意指令的两个操作对象位数应当一致,如
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指令可以完成两种传送:
- 将数据直接送入寄存器
- 将一个寄存器中的内容送入另一个寄存器
- 也可以将一个内存单元中的内容送入一个寄存器中
[...]
表示一个内存单元,其中的内容表示内存单元的偏移地址- 8086CPU自动取DS中的数据作为内存单元的段地址
- 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操作分析
- SP=SP-2,SS:SP只想当前栈顶前面的单元,以当前栈顶前面的单元为心的栈顶
- 将ax中的内容送入SS:SP指向的内存单元,SS:SP此时指向新栈顶
如果将10000H~1000FH这段空间当做栈,初始状态栈是空的,此时SS=1000H,那么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个字节)