我正在查看一些x86代码,我相信它们是使用Microsoft工具链构建的,并且试图弄清楚此调用过程中使用的调用约定:函数FOO像这样开始:

   push esi ; save ESI (it gets restored later)
   lea esi, [ebp-0xC] ; set param 1 for call to FOO
   call FOO
   test eax, eax ; test return value
   jz somelabel


由于ESI尚未在FOO主体中初始化,因此我假设调用者将其作为参数传递。 br />
这叫什么约定?它似乎是fastcall的变体。此约定有名称吗?

评论

它不是通过参数传递的结构吗? esi将是基址,对每个字段的访问将通过几个偏移量传递。不是吗?

是的,该参数是指向调用方的局部变量(12字节结构)的指针,但是将该指针作为参数传递给FOO的调用约定是什么?

#1 楼

没有像这样的“官方”调用约定。您所看到的很可能是链接时代码生成的结果,也称为LTO(链接时优化)或WPO(整个程序优化)。

启用此功能后,优化当编译器可以访问整个程序和所有编译单元的代码,并且可以使用此信息进行更极端的优化时,代码将在链接时完成。

从MSDN:


当/ LTCG用于链接使用/ Og,/ O1,/ O2或
/ Ox编译的模块时,将执行以下优化:


跨模块内联
过程间寄存器分配(仅64位操作系统)
自定义调用约定(仅x86)
TLS位移小(仅x86)
堆栈双对齐(仅x86)
改进的内存歧义消除(更好的全局变量和输入参数干扰信息)



在代码片段中,您引用了检测到的编译器那不会从程序外部调用函数FOO,因此可以将调用约定自定义为使用已在调用位置设置的寄存器值的调用约定,或改善寄存器分配。使用大量模板化的代码,您甚至可以获得经常使用的函数的多个副本,这些函数在不同的寄存器和/或堆栈集中接受参数。

评论


什么是“堆栈双重对齐”?

– newgre
13年8月23日在8:22

不确定,但是也许他们的意思是如果他们知道在调用该函数的每个位置都已经对齐了SSE数据的每个函数,则不必重新对齐堆栈。

–伊戈尔·斯科钦斯基♦
13年8月23日在10:59

不仅是SSE数据,而且还有8字节对齐效果更好的任何数据(例如,双基元)。请参阅此有价值的帖子,该帖子似乎来自Microsoft员工,以获取每个LTCG优化的描述。 codeproject.com/Articles/1660/…

–ajs410
2013年12月12日0:25