首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

汇编: 啥是易失寄存器啊(Volatile )。解决办法

2014-01-01 
汇编: 啥是易失寄存器啊(Volatile )。本帖最后由 TheNewIpad 于 2013-12-10 10:54:14 编辑VS9中64位汇编中

汇编: 啥是易失寄存器啊(Volatile )。
本帖最后由 TheNewIpad 于 2013-12-10 10:54:14 编辑 VS9中64位汇编中说了,

MSDN 说了
易失寄存器是由调用方假想的临时寄存器,并要在调用过程中销毁。
非易失寄存器需要在整个函数调用过程中保留其值,并且一旦使用,则必须由被调用方保存。
(Volatile registers are scratch registers presumed by the caller to be destroyed across a call. Nonvolatile registers are required to retain their values across a function call and must be saved by the callee if used.)

(MSDN)还说
寄存器 RAX、RCX、RDX、R8、R9、R10、R11 被视为易失的,并且必须在函数调用时视为已销毁(除非通过全程序优化等分析被认定为安全的)。

MSDN又说 前 4 个整型参数传入 RCX、RDX、R8 和 R9 中。其他参数传递到堆栈中。


矛盾出来了。
先说 易失寄存器是调用过程中销毁,  还说, RCX RDX,R8, R9 是易失的。 又说RCX, RDX,R8, R9是传递整型参数。  

直白的理解, R8,R9 传递给参数后,这些寄存器就销毁了。。。。

我就想,我还没用,或者没放到栈上呢,你销毁呢。 我用啥。

所以想知道,啥是易失寄存器。 
[解决办法]
《计算机组成原理》
[解决办法]

64 Bits         32Bits  
RAX,           Eax
RCX,           Ecx
RDX             Edx 
这是互相对应的
C++
eax 用来传递返回值
ecx 用来传递this指针
edx 用来配合eax,传递超长返回值(64 比如 long long)

估计64 Bits 寄存器和对应的32Bits寄存器的作用也差不多。
这些
至于R8,R9,R10,R11 是函数代码会随时用到的寄存器。
Rax,Rcx,Rdx 也是计算中经常用到的。

所以这些寄存器,不是可以随便用的,
里面的值会被编译器,随便安排代码改写的。
所以这些寄存器是随时会使用的,即易失的,
如果你的嵌入汇编语句也使用它们,记得要保护寄存器。
不然里面的值,会随时被修改。


至于传递参数,RCX 对于C++可能是经常会用的。
RDX,R8,R9 只是,某些特殊的调用约定(或者特殊的返回值),才会用于传递参数。

其实这都没有关系,这些寄存器是随时会改变的,只是参数传递的到函数以后,保存一下这些寄存器的值即可。
实际上,程序运行中寄存器的压栈出栈,是经常会发生的操作,所以这些并不矛盾。

参数传递只是在这个寄存器,没有另作他用时,可以得到传入的实参;
而有些寄存器用作返回值寄存器而已,----只需要函数返回时填入返回值即可。





[解决办法]
易失寄存器:你可以随意使用,不用恢复它的初始值(你使用它之前包含的数据)
非易失寄存器:你使用之前要保存它的初始值,使用之后要恢复

[解决办法]
MS非整个名词(volatile)出来迷惑众生。 这实际是调用约定的事,不是汇编的事。 这里说的易失是指函数(或过程)可以随意使用而无需恢复原始值(调用开始时的值)的寄存器。因为调用方在调用了别的函数数,这些寄存器的值很可能已经被修改,所以叫“易失”。

当函数A要调用函数B时,在执行调用指令之前,A必须把易失寄存器的值保存起来(除非A确定这些值在调用结束后不再需要),调用开始后,函数B可以随意使用这些寄存器,调用结果后,函数A需要自己去恢复这些寄存器的值。

对于非易失,被调用函数要么不修改,要么在修改前保存原值,并调用结束前恢复原值。 这种寄存器调用方在调用结束后可以继续使用而不用担心其值有变动。
[解决办法]
引用:
Quote: 引用:

64 Bits         32Bits  
所以这些寄存器,不是可以随便用的,
里面的值会被编译器,随便安排代码改写的。
所以这些寄存器是随时会使用的,即易失的,


说的吓人,我汇编写的代码,用人的A寄存器,编译器给我改了? 这编译器还能用么?


你可以保护以下,另外64Bits 一共16个寄存器,这里只提到8个左右,寄存器够你用的。
我所说的编译器会安排代码,是指嵌入汇编,一般会和C,C++代码混合写在,在一个函数中,

函数中其他代码(C,C++部分,和一部分自动生成的代码 ),可能会使用这些易失的寄存器,
那么你要是还是依赖,那个存储器的话,你的代码就废了。

比如 

__asm mov rax ,0
int a[10]={10};
int b = 20;
b += 20;//这个代码也许就用到易失的寄存器rax了
你现在还认为 rax =8
int x;
__asm mov x,rax;

return a[x];//在这里期待返回a[0] == 10; 就可能不对了。



 
 



[解决办法]
建议楼主不必纠结于这些名词,如果你有了一定的汇编程序实践,这个东西自然明了。

热点排行