设为首页 加入收藏

TOP

8.2.1 数据寄存器
2013-10-07 00:51:10 来源: 作者: 【 】 浏览:61
Tags:8.2.1 数据 寄存器

8.2  编程(www.cppentry.com)环境

x87 FPU有专用的指令和配套的寄存器。它的指令是x87浮点指令,配套的寄存器有:8个80位的数据寄存器、1个16位的控制寄存器、1个16位的状态寄存器、1个16位的标志寄存器、1个最后指令地址寄存器、1个最后操作数寄存器、1个操作码寄存器。其中,最后3个寄存器用于最后一次操作的信息记录,主要用于异常处理。如图8-1所示。

 

编程(www.cppentry.com)主要是围绕数据寄存器堆栈、状态寄存器和控制寄存器进行的,其他部分则多用于调试支持。

8.2.1  数据寄存器

x87 FPU有8个80位的数据寄存器(编号0~7),使用IEEE扩展双精度格式存储操作数,如图8-1所示。当内存中的数据载入数据寄存器时,如果数据格式不是扩展双精度格式,则在载入过程中进行格式转换。输出过程也是如此。

8个数据寄存器组成一个循环堆栈,栈顶记录保存于状态寄存器中,相当于堆栈指针。每次压栈(FLD指令载入数据),堆栈指针就减1,在0~7之间循环。代码并不直接使用这个指针操作这些寄存器,而是使用ST(0)~ST(7)表示。ST(0)指栈顶,即状态寄存器中栈顶指针指示的那个寄存器。如图8-2所示。

 

假设当前状态寄存器中的栈顶指针是N(即编号N的寄存器位于栈顶),则ST(i)对应的寄存器编号是:N+i mod 8

例如初始状态时,堆栈指针是0,FLD指令装载了一个数据以后,指针减小1是7,则ST(0)即是寄存器7,而ST(1)对应的寄存器编号是:7+1 mod 8 = 0

这些计算实际上是以CPU管理寄存器的方式看待这8个寄存器组成的堆栈,比较晦涩。还有一种方式不是从CPU角度理解,而是从指令角度(也就是编程(www.cppentry.com)角度)理解,直接将ST(0) ~ST(7)看成一个堆栈,ST(0)是栈顶,每次压栈,数据向上移动一个寄存器。例如载入一个数据,这个数据在ST(0)中,再次载入一个数据,则当前数据在ST(0)中,而上次载入的数据在ST(1)中。这种理解方式相对简易。

x87 FPU的数据寄存器是相对独立的,不受过程调用的影响。在线程、进程切换时,操作系统会保护这些寄存器,因此它们也不受线程、进程切换的影响。这意味着这些寄存器是个存放数据和传送参数的好地方,例如VC6就将ST(0)作为浮点返回值的存放场所。

绝大部分浮点指令都会影响数据寄存器,影响是多方面的:数据寄存器的内容、堆栈指针、标志寄存器等都会改变,例如FSIN指令就改写ST(0),自然标志寄存器也随之改变,其影响类似伪码:

  1. ST(0) = FSIN( ST(0) )  
  2. TAG(0)= class( ST(0) ) 

而FINCSTP则仅改变指针,类似:

  1. TOP = TOP + 1 

当然,大部分指令的影响要比这些复杂,例如FADDP指令,在使用时需要仔细阅读指令说明。

有一个细节需要注意,即通常使用FLD指令载入数据进行计算,使用FSTP等数据输出结果,但有时不需要输出数据寄存器(例如逻辑比较操作),而只是清空时,不能使用FINCSTP指令。虽然FINCSTP指令修改堆栈指针,但标志寄存器没有改变,因此堆栈并未清空。一个简单的方法是使用下列指令:

  1. FSTP ST(0) 

数据寄存器、堆栈、标志寄存器等之间是联动的,在一般情形下,用户只需关注自己的数据处理逻辑,无需关注它们之间关系的细节,同时也应尽量避免干预(例如直接修改堆栈指针)。一个简单的指导原则就是将堆栈指针和标志寄存器当作只读的,仅用于调试。

还有一点需要特别注意,那就是MMX的数据寄存器与x87 FPU的数据寄存器虽然名字不同,实际上却是通过别名机制共用数据寄存器。这意味着,MMX指令和x87 FPU指令存在资源共享问题,不可同时使用。

【责任编辑:董书 TEL:(010)68476606】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇8.2.2 状态寄存器 下一篇2.2.2 Visual C++代码编辑器

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: