Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly SystemV(x86_64)abi调用约定:调用方保存的变量是否应保存在递归调用中(即使它们没有更改)?_Assembly_X86 64_Calling Convention_Att_Abi - Fatal编程技术网

Assembly SystemV(x86_64)abi调用约定:调用方保存的变量是否应保存在递归调用中(即使它们没有更改)?

Assembly SystemV(x86_64)abi调用约定:调用方保存的变量是否应保存在递归调用中(即使它们没有更改)?,assembly,x86-64,calling-convention,att,abi,Assembly,X86 64,Calling Convention,Att,Abi,假设我想实现一个函数,用于对给定范围内的数字求和: int-sumRange(int-start,int-end); 这就是我提出的实现:(AT&T asm语法) sumRange: cmp%edi,%esi jl返回0如果开始>结束则跳转 #预约: 推送%edi 电子数据交换公司 #推送%esi 呼叫sumRange #投递电话: #pop%esi pop%edi 添加%edi,%eax ret#返回开始+结束范围(开始+1,结束) 归零: 异或%eax,%eax 返回#返回0 请注意,%

假设我想实现一个函数,用于对给定范围内的数字求和:

int-sumRange(int-start,int-end);
这就是我提出的实现:(AT&T asm语法)

sumRange:
cmp%edi,%esi
jl返回0如果开始>结束则跳转
#预约:
推送%edi
电子数据交换公司
#推送%esi
呼叫sumRange
#投递电话:
#pop%esi
pop%edi
添加%edi,%eax
ret#返回开始+结束范围(开始+1,结束)
归零:
异或%eax,%eax
返回#返回0
请注意,%edi和%esi都是调用方保存的寄存器。 %edi在sumRange的不同递归级别的帧之间发生更改,因此它必须保存在预调用中,但%esi在递归调用中没有更改-因此代码在不保存该寄存器的情况下仍能工作

问题是:该代码是否符合SystemV约定

我认为它不是:
该公约不考虑注册函数的实际更改(如我所发现的)。 因此,我们需要假设所有调用方保存的寄存器在函数调用后都可能发生更改


此外,即使我们在递归调用后不使用%esi,我也希望%esi在整个sumRange范围内具有适当的值。

这是对同一函数的递归调用,因此您知道实现。你不需要做任何假设。从顶级外部调用方的角度来看,您的函数遵循ABI。对于递归调用来说,这并不重要(但如果以后碰巧更改了实现,可能会使维护代码变得更加困难)。您不需要保存
end
,但这不是因为它没有被修改。您不需要保存它,因为您将它未经修改地传递给您调用的函数,并且在递归调用之外不使用它。被调用函数是否修改它并不重要,该变量已经失效。@yosef惯例是,您需要保存调用方保存的变量,这些变量在调用后仍然有效。不多也不少。调用是否为递归并不重要。从符合调用约定的角度来看,重要的是保留被调用方保存的所有寄存器(rbx、rbp、r12-r15)。而你是这样做的——你从来没有修改过它们中的任何一个。递归和非递归之间没有区别。如何管理调用者保存的寄存器对函数的正确性很重要,但对ABI合规性不重要。也许术语“调用者保存”让您感到困惑?这并不意味着您在进行函数调用时必须绝对保存该寄存器-您只需要在调用返回后使用它的值时保存它。有些人更喜欢术语“call clobbered”,它只是说明在调用前后寄存器发生了什么-它的值可能被覆盖-而不是告诉您应该如何处理它。