寄存器

学习内容:从内存角度继续学习寄存器。
内存单元是字节单元(一个单元存放一个字节),则一个字要用两个地址连续的内存单元来存放。这个字的低位字节存放在低地址单元中,高位字节存放在高地址单元中。
字单元:存放一个字型数据的内存单元。由两个地址连续的内存单元组成。
我们将起始地址为N的字单元简称为N地址字单元。
8086CPU中有一个DS寄存器,通常用来存放要访问数据的段地址。
mov指令还可以将一个内存单元中的内容送入一个寄存器中。但在指令中必须指明:寄存器用寄存器名来指明,内存单元用内存单元的地址来指明。格式:
 mov 寄存器名  内存单元地址
对于偏移地址:[...]表示一个内存单元,[x]中的x表示内存单元的偏移地址。
对于段地址:指令执行时,8086CPU自动取ds中的数据为内存单元中的段地址。
8086不支持将数据直接送入段寄存器的操作,所以不允许这样的操作:mov  ds  1001H。合法的做法是:用一个寄存器来中转,即将1001H送入到一个一般的寄存器,例如bx,再将bx中的内容送入到ds。
示例(将内存中的数据读到寄存器中):
 mov   bx , 1001H 
 mov   ds ,  bx
 mov   ax ,  [0]
既然有"mov 段寄存器,寄存器",从寄存器向段寄存器传送数据,那么也有"mov 寄存器  段寄存器",从段寄存器向寄存器传送数据。
既然有"mov 内存单元,寄存器",从寄存器向内存单元传送数据,也有"mov 内存单元 ,段寄存器",从段寄存器向内存单元传送数据。当然还有"mov  段寄存器 内存单元"。
add和sub指令同mov一样,都有两个操作对象。它们也可以有以下几种形式:
 add  寄存器,数据 
 add  寄存器,寄存器
 add  寄存器,内存单元
 add  内存单元,寄存器
 sub   寄存器,数据
 sub   寄存器,寄存器
 sub   寄存器,内存单元
 sub   内存单元,寄存器
但是add和sub两种运算不可以对段寄存器进行操作。
栈是一种具有特殊的访问方式的存储空间。它的特殊性在于,最后进入这个空间的数据,最先出去。
栈有两个基本的操作:入栈和出栈。入栈就是将一个新的元素放到栈顶,出栈就是取出一个元素。栈顶的元素总是最后入栈,需要出栈时,又总是最先被从栈中取出。栈的这种操作被称为:LIFO(Last in first out)。
8086CPU提供相关的指令来以栈的方式访问内存空间。我们在基于8086CPU编程时,可以将一段内存当作栈来使用。
8086CPU提供入栈和出栈指令,最基本的两个是:PUSH(入栈)和POP(出栈)。
push ax等入栈指令执行时,要将寄存器中的内容放入到当前栈顶单元的上方,成为新的栈顶元素;pop ax等指令执行时,要从栈顶单元取出数据,送入寄存器中显然,push和pop在执行的时候都必须知道哪个单元是栈顶单元。
CPU如何知道栈顶的位置?:8086CPU中,有两个寄存器,段寄存器SS和寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在SP中。
任意时刻,SS:SP指向栈顶元素。push和pop指令执行时,CPU从SS和SP得到栈顶的地址。
push ax的执行由以下两步完成:
 ~SP=SP-2,SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为为新的栈顶;
 ~将ax中的内容送入SS:SP指向的内存单元处,SS:SP指向新栈顶。
注意!!:如果我们将10000H~1000FH这段空间当做栈,初始状态栈是空的,此时,SS=1000H,则SP=?
 解答:我们将10000H~1000FH这段空间看作栈,SS=1000H,栈的空间大小为16字节,栈最底部的字单元地址为1000:000E。任意时刻,SS:SP指向栈顶,当栈中只有一个元素的时候,SS=1000,SP=000EH。栈为空,就相当于栈中的唯一元素出栈,出栈后,SP=SP+2,SP原来为000EH,加上2后变成0010H,所以当栈为空的时候,SS=1000H,SP=0010H。
pop ax的执行由以下两步完成:
 ~将SS:SP指向的内存单元内容送入到寄存器中;
 ~SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新栈顶。
栈顶超界是危险的。然而8086CPU不保证我们对栈的操作不会超界。
用栈来暂存以后需要恢复的寄存器中内容时,出栈的顺序要和入栈的顺序相反,因为最后入栈的寄存器的内容在栈顶,所以要恢复时,应该先出栈。
pop和push实际上是一种内存传送指令。
我们可以将长度为N(N<=64KB)的一组连续地址、起始地址为16的倍数的内存单元,当做栈空间来使用。
将一段内存当作栈段,仅仅是我们在编程时的一种安排,CPU并不会由于这种安排,就在执行pop、push等栈操作指令时就自动地将我们定义的栈段当做栈空间来访问。
一个栈段最大可以设为多少?::
 从栈操作指令所完成的功能角度来看,push和pop等指令在执行时只能修改SP,所以栈顶的变化范围为:0~FFFFH,从栈空的时候SP=0,一直压栈,直到栈满时SP=0;如果再次压栈,栈顶将环绕,覆盖了原来栈中的内容。所以一个栈的容量最大为64KB。


寄存器是CPU内部重要的数据存储资源,主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间,也就是说CPU操作寄存器比操作内存快(寄存器是直接存取,而内存是寻址存取)。

汇编比C语言效率高,经常操作寄存器也是一个原因吧。

 

C语言可以把变量定义为寄存器类型的,将数据直接存放在CPU的寄存器中,使用关键字register定义变量

例如register a=123;定义a为寄存器类型变量。

 

对于register变量需要注意的几点:

(1)使用register定义的变量尽可能存放到寄存器中,但不绝对。

(2)定义的变量一般整数(int)为宜。

(3)定义的变量,只要涉及到该变量的地址时,编译器都会报错,如"&a",数组首地址a。

(4)也可以定义指针类型的变量,如register *ptr=&c,c="abcde",c不是register变量。*ptr='a',ptr++移动4个字节。

(5)不能使用sizeof(register)。

你可能感兴趣的:(寄存器)