汇编语言学习笔记二:访问内存的寄存器
1、通过前一篇章的学习,知道CS和IP寄存器的内容合成的物理地址指向的是执行指令的地址。而访问内存也需要知道内存的地址,内存地址也是由段地址和偏移地址组成,8086CPU中默认存放内存地址段地址的寄存器是DS寄存器,偏移地址则是由[n]表示,n表示偏移量。例子:
MOVBX,1000H //将1000H存放到BX寄存器当中
MOVDS,BX //将BX中的值(1000H)存放到段寄存器DS中
MOVAL,[0] //注意这里,既然是AL,那么移动是以字节为单位,
//因为AL为AX的低位,长度为8位。[0]表示内存
//偏移地址是0H,默认段地址为DS中的值1000H,
//整体意思是将10000H中的数据存放在AL中。
(1)要注意,数据和段寄存器直接是不能直接传递的,因此必须以普通寄存器为中介,现将数据存入通用寄存器,再将通用寄存器的数据传入段寄存器中。
(2)假如第三条指令是MOV AX,[0],那么就是传递一个字的内容,就是将10000H和10001H中的数据总计16位存入寄存器AX当中。
2、内存单元(以字节为单位)存储数据时,是以字节为单位存放,存放的形式与系统是大端还是小端有关。小端是低地址存放低位字节,高地址存放高位字节;大端则是低地址存放高位字节,高地址存放低位字节。这里讲的8086是小端系统。8086的寄存器是16位。那么一次性可以存放一个字(两个字节)。而存放一个字是用两个地址连续的内存单元来存放,由低地址到高地址,分别存放字的低位到高位。
3、MOV指令除了不能将数据直接存入段寄存器之外,寄存器和寄存器、段寄存器和寄存器、内存单元和寄存器、内存单元和段寄存器之间都可以传递数据(反过来也可以)。
4、栈有两个基本的操作:入栈和出棧。都只和栈顶有关,入栈就是将新的数据放到栈顶,出棧就是从栈顶取出一个元素,那么栈的这种操作就是LIFO(后进先出)。CPU也提供栈机制,并且有两个相关的指令PUSH和POP。PUSH表示入栈,POP表示出棧。CPU的入栈出棧操作都是以字(非字节)为单位。具体执行过程可以见下图:
(1)图1表示初始状态栈顶地址为10010H,由图1到图4得知,当需要入栈时,先将栈顶地址减去2个字节(以字为单位),得到1000EH,然后在1000EH存放数据的低位(低地址低位),1000FH存放数据的高位(高地址高位),此时栈顶地址为1000EH。由此可知,栈顶地址存放有数据,要想PUSH,必须先让栈顶地址减2,再存放数据。(先减地址存放数据)
(2)而图5到图7可以直到,出棧操作与入栈操作相反,先将栈顶数据出棧,然后再让栈顶地址加上2个字节。(先取数据再加地址)
(3)由此可知,栈数据增加的过程是地址由高到低的过程。
5、CS和IP合成的地址内是需要执行的指令,DS和[n]合成的地址内是内存访问的地址。那么栈顶地址的段地址和偏移地址存放在哪呢?答案是SS段寄存器和SP寄存器。任意时候,SS:SP都指向栈顶地址(入栈的时候,记得现将栈顶地址减2)。
6、栈的空间大小应当有个范围,那么入栈和出棧就会有越界的风险,然而8086CPU并没有相应的措施阻止越界操作。栈空间之外存放的是数据、代码。假如越界而将数据、代码意外的改写,将会引起一连串的错误,所以程序员自身要尽量避免越界。
7、push和pop操作可以对寄存器、段寄存器、内存单元使用。