Assembly 什么是被叫方和被叫方保存的寄存器?

Assembly 什么是被叫方和被叫方保存的寄存器?,assembly,cpu-registers,calling-convention,abi,Assembly,Cpu Registers,Calling Convention,Abi,我很难理解调用者和被调用者保存的寄存器之间的区别以及何时使用什么 我正在使用MSP430 : 程序: mov.w #0,R7 mov.w #0,R6 add.w R6,R7 inc.w R6 cmp.w R12,R6 jl l$loop mov.w R7,R12 ret 上面的代码是一个被调用方,在教科书示例中使用过,因此它遵循约定。R6和R7保存呼叫者,R12保存呼叫者。我的理解是,被调用方保存的regs不是“全局”的,因为在过程中更改其值不会影响过程外的值。这就是为什么您必须在

我很难理解调用者和被调用者保存的寄存器之间的区别以及何时使用什么

我正在使用MSP430 :

程序:

mov.w #0,R7 
mov.w #0,R6 
add.w R6,R7 
inc.w R6 
cmp.w R12,R6 
jl l$loop 
mov.w R7,R12
ret
上面的代码是一个被调用方,在教科书示例中使用过,因此它遵循约定。R6和R7保存呼叫者,R12保存呼叫者。我的理解是,被调用方保存的regs不是“全局”的,因为在过程中更改其值不会影响过程外的值。这就是为什么您必须在开始时将新值保存到被调用方注册表中

R12,由于缺少更好的词语,调用方保存为“全局”。调用后,程序所做的操作对R12有持久的影响


我的理解正确吗?我是否遗漏了其他内容?

被叫方与被叫方保存是一种约定,由谁负责在调用中保存和恢复寄存器中的值。所有寄存器都是“全局”的,因为任何地方的任何代码都可以看到(或修改)寄存器,并且这些修改将被以后任何地方的代码看到。寄存器保存约定的要点是,代码不应修改某些寄存器,因为其他代码假定值未修改

在您的示例代码中,没有任何寄存器被调用为save,因为它不会尝试保存或还原寄存器值。但是,它似乎不是一个完整的过程,因为它包含到未定义标签(
l$loop
)的分支。因此,它可能是将某些寄存器视为被调用方保存的过程中间的一段代码;您只是缺少保存/还原说明

调用方保存的寄存器(又称volatile寄存器,或调用被删除)用于保存需要的临时数量 不能跨调用保留

因此,如果调用方希望在过程调用后恢复该值,则调用方有责任将这些寄存器推送到堆栈上或将它们复制到其他地方

不过,让
调用
销毁这些寄存器中的临时值是正常的

被调用方保存的寄存器(也称为非易失性寄存器,或调用保留的)用于保存应 在通话中被保留


当调用者进行过程调用时,可以预期这些寄存器在被调用者返回后将保持相同的值,这使得被调用者有责任在返回调用者之前保存并恢复它们。或者不要碰它们。

调用方保存的/被调用方保存的术语是基于一个相当愚蠢、效率低下的编程模型,调用方实际上保存/恢复了所有被调用的寄存器(而不是在别处保留长期有用的值),而被调用方实际上保存/恢复了所有被调用的寄存器(而不是只是不使用其中的一些或任何一个)

或者,您必须理解“调用方保存”的意思是“如果以后需要值,则以某种方式保存”

事实上,高效的代码可以让值在不再需要时被销毁。编译器通常在函数开始时生成一些保存调用的寄存器的函数(并在函数结束时还原)。在函数内部,它们使用这些寄存器来处理需要在函数调用之间保留的值

我更喜欢“保留呼叫”和“取消呼叫”,这两个词在你听到基本概念后都是明确的和自我描述的,并且不需要从呼叫方或被呼叫方的角度去思考任何严肃的心理体操。(两个词都来自同一个角度)

此外,这些术语的差异不止一个字母

术语volatile/non-volatile相当不错,与是否会因断电而失去价值的存储类似(比如DRAM与Flash)。但是C
volatile
关键字具有完全不同的技术含义,因此在描述C调用约定时,这是“(non-volatile)”的缺点


  • 调用被关闭、aka调用方保存易失性寄存器适用于下一次函数调用后不需要的临时值
从被调用方的角度来看,您的函数可以自由覆盖(也称为clobber)这些寄存器,而无需保存/恢复

从调用者的角度来看,
callfoo
会销毁(也称为clobbers)所有被调用的寄存器,或者至少你必须假设它会

您可以编写具有自定义调用约定的私有助手函数,例如,您知道它们不修改某个寄存器。但是如果您知道(或希望假定或依赖)所有这些函数如果目标函数遵循正常的调用约定,那么您必须将函数调用视为破坏了所有被调用的寄存器。这就是名称的字面含义:调用会破坏这些寄存器

一些进行过程间优化的编译器还可以使用自定义调用约定创建不遵循ABI的函数的内部仅供使用的定义

  • 保留调用,又称保存被调用方非易失性寄存器在函数调用中保留它们的值。这对于进行函数调用的循环中的循环变量,或者通常非叶函数中的任何内容都很有用
从被调用方的角度来看,除非将原始值保存在某个位置,以便在返回之前还原,否则无法修改这些寄存器。或者对于堆栈指针之类的寄存器(几乎总是保留调用),您可以减去已知偏移量并在返回之前将其重新添加,而不是实际将旧值保存在任何位置。也就是说,您可以通过推算航位来恢复它,除非您分配运行时变量st