什么编译器使用调用约定,使用 EAX 作为第一个参数,然后压入堆栈?

逆向工程 C++ 调用约定
2021-06-28 16:36:00

我最近问了一个问题:一个看似用 MSVC 编译的 IA-32 程序如何通过 EAX 发送它的唯一参数?发布问题后,我发现另一个函数传入了第一个参数EAX,然后推送了其剩余的参数。然后调用者清理堆栈。

调用代码:

.text:00402465                 lea     eax, [ebp+var_4]
    ...
.text:00402469                 push    eax
.text:0040246A                 mov     eax, [ebp+hWnd]
.text:0040246D                 call    openFileDialog
.text:00402472                 add     esp, 4

和函数本身:

.text:00411730 openFileDialog  proc near
.text:00411730
    ...
.text:00411730 arg_0           = dword ptr  8
.text:00411730
.text:00411730                 push    ebp
.text:00411731                 mov     ebp, esp
.text:00411733                 sub     esp, 18h
.text:00411736                 cmp     byte_42AE1D, FALSE
.text:0041173D                 push    ebx
.text:0041173E                 push    esi
.text:0041173F                 push    edi
.text:00411740                 mov     esi, eax
    ...
.text:00411789                 mov     eax, [ebp+arg_0]
.text:0041178C                 push    eax
.text:0041178D                 push    esi
.text:0041178E                 call    openFileDialog_Compat
.text:00411793                 add     esp, 8

如您所见,在函数中, 的值EAX在任何影响它之前保存,因此它肯定被用作参数。稍后,推送的参数被传递给一个普通的 __cdecl 函数。

该程序链接到使用 msvcr100.dll 并始终使用 MSVC 样式(例如 __security_cookie、MSVC 名称修改等),因此它似乎是使用 Visual C++ 编译的,但这种不寻常的调用约定让我对此表示怀疑。

2个回答

这可能是使用“整体程序优化”或“链接时代码生成”编译的程序。从 MSDN

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

  • 跨模块内联
  • 过程间寄存器分配(仅限 64 位操作系统)

  • 自定义调用约定(仅限 x86)

  • 小 TLS 位移(仅限 x86)

  • 堆栈双对齐(仅限 x86)

  • 改进的内存消歧(更好的全局变量和输入参数的干扰信息)

检查msvc 支持的调用约定至于函数名openFileDialog,是ac#func?通过 CLR 结合 C# 和 C++??奇怪的事情可能会发生。MS 不需要向公众公开这些细节。