GCC忽略cdecl?

GCC忽略cdecl?,gcc,calling-convention,Gcc,Calling Convention,我在Linux x86上使用gcc。 我的程序将指向C函数的指针导出到LLVM JIT函数。调用约定是cdecl。它在MingW和Windows上运行良好。但在linux x86平台上会发生奇怪的事情。导出的C函数的反汇编如下: push ebp mov ebp,esp push ebx sub esp,0x34 mov eax,0xfffffffc mov eax,DWORD PTR gs:[eax] mov eax,DWORD PTR [eax+0x1c

我在Linux x86上使用gcc。 我的程序将指向C函数的指针导出到LLVM JIT函数。调用约定是cdecl。它在MingW和Windows上运行良好。但在linux x86平台上会发生奇怪的事情。导出的C函数的反汇编如下:

push   ebp
mov    ebp,esp
push   ebx
sub    esp,0x34
mov    eax,0xfffffffc
mov    eax,DWORD PTR gs:[eax]
mov    eax,DWORD PTR [eax+0x1c]
mov    eax,DWORD PTR [eax]
mov    eax,DWORD PTR [eax+0x28]
mov    edx,DWORD PTR [ebp+0xc]
shl    edx,0x4
add    eax,edx
mov    DWORD PTR [ebp-0xc],eax
mov    edx,DWORD PTR ds:0x8e49940
mov    ebx,DWORD PTR [ebp+0x8]
lea    eax,[ebp-0x20]
mov    ecx,DWORD PTR [ebp-0xc]
mov    DWORD PTR [esp+0xc],ecx
mov    ecx,DWORD PTR [ebp+0x10]
mov    DWORD PTR [esp+0x8],ecx
mov    DWORD PTR [esp+0x4],edx
mov    DWORD PTR [esp],eax
call   0x8090f6f <SoCreateArray(DVM_VirtualMachine_tag*, int, DVM_TypeSpecifier_tag*)>
sub    esp,0x4
mov    eax,DWORD PTR [ebp-0x20]
mov    edx,DWORD PTR [ebp-0x1c]
mov    DWORD PTR [ebx],eax
mov    DWORD PTR [ebx+0x4],edx
mov    eax,DWORD PTR [ebp+0x8]
mov    ebx,DWORD PTR [ebp-0x4]
leave
ret    0x4
请注意,反汇编代码的最后一条指令是“ret 0x4”,这意味着它会自动清理堆栈,而不是cdecl函数!更重要的是,即使我这样声明C函数:

DVM_ObjectRef SoNewArray(BINT ty,BINT dim)属性((cdecl))

结果是一样的。也许GCC优化了我的代码,并自动使用stdcall,而忽略了调用约定

我的GCC命令是


gcc-Wall-feexceptions-Wfatal errors-g

我的64位linux上的gcc 5.4.0需要
\uuuu属性((\uuu-cdecl\uuuu))

#ifdef __GNUC__
#define _cdecl __attribute__((__cdecl__))
#endif

//sometime later
int _cdecl AddItemVar(void *AContext,void *AFun,long ACfg1,...);
该代码最初来自于uu BORLANDC uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。编译会产生以下警告:

../../LIB/DevOS.C/DevOS.h:242:64:警告:“cdecl”属性 忽略[-Wattributes]

下面是一个来自“智湖”的答案,一个中国人的“Stackoverflow”。谢谢你 RednaxelaFX@zhihu。我发现这个问题的真正原因是函数返回的是结构而不是基本类型。 请参见函数声明:

DVM_ObjectRef SoNewArray(BINT ty,BINT dim)
DVM_ObjectRef是一种结构。当x86 gcc处理上述函数时,它实际上会生成:

DVM_ObjectRef SoNewArray(DVM_ObjectRef * ret,BINT ty,BINT dim)
请参阅有关x86调用约定的更多详细信息:


我还发现,该程序还将eax(mov DWORD PTR[esp],eax)推到“调用”指令之前。如果我编译一个简单的“hello world”C程序,它最终不会在“调用”sSo之前推送eax,GCC会忽略
\uu cdecl
?仍然没有回答。直呼是中文堆栈交换,但堆栈溢出
DVM_ObjectRef SoNewArray(DVM_ObjectRef * ret,BINT ty,BINT dim)