我在Linux x86上使用gcc。 我的程序将指向C函数的指针导出给LLVM JIT函数。调用约定是cdecl。它在Windows上的MingW上运行良好。但在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
以下是 C 语言的源代码:
DVM_ObjectRef SoNewArray(BINT ty,BINT dim)
{
DVM_TypeSpecifier *type
= &curthread->current_executable->executable->type_specifier[ty];
DVM_ObjectRef barray;
barray = SoCreateArray(curdvm, dim, type);
return barray;
}
请注意反汇编代码的最后一条指令是“ret 0x4”,这意味着该函数本身清除堆栈,并且不是一个cdecl函数!更重要的是,即使我像这样声明C函数:
DVM_ObjectRef SoNewArray(BINT ty,BINT dim) attribute((cdecl));
结果也是相同的。也许GCC优化了我的代码,自动使用stdcall,忽略调用约定?
我的GCC命令是
gcc -Wall -fexceptions -Wfatal-errors -g
__cdecl
呢?仍未得到答复。 - mireazma