我有一个奇怪的错误。我有一个由一个编译器(在本例中为 msvc)编译的模块,它调用从另一个由单独的编译器(TCC)编译的模块加载的代码。
tcc 代码提供了一个回调函数,两个模块的定义如下:
typedef float( * ScaleFunc)(float value, float _min, float _max);
MSVC 代码调用代码如下:
finalValue = extScale(val, _min, _max);
000007FEECAFCF52 mov rax,qword ptr [this]
000007FEECAFCF5A movss xmm2,dword ptr [rax+0D0h]
000007FEECAFCF62 mov rax,qword ptr [this]
000007FEECAFCF6A movss xmm1,dword ptr [rax+0CCh]
000007FEECAFCF72 movss xmm0,dword ptr [val]
000007FEECAFCF78 mov rax,qword ptr [this]
000007FEECAFCF80 call qword ptr [rax+0B8h]
000007FEECAFCF86 movss dword ptr [finalValue],xmm0
TCC编译出来的函数是这样的:
float linear_scale(float value, float _min, float _max)
{
return value * (_max - _min) + _min;
}
0000000000503DC4 push rbp
0000000000503DC5 mov rbp,rsp
0000000000503DC8 sub rsp,0
0000000000503DCF mov qword ptr [rbp+10h],rcx
0000000000503DD3 mov qword ptr [rbp+18h],rdx
0000000000503DD7 mov qword ptr [rbp+20h],r8
0000000000503DDB movd xmm0,dword ptr [rbp+20h]
0000000000503DE0 subss xmm0,dword ptr [rbp+18h]
0000000000503DE5 movq xmm1,xmm0
0000000000503DE9 movd xmm0,dword ptr [rbp+10h]
0000000000503DEE mulss xmm0,xmm1
0000000000503DF2 addss xmm0,dword ptr [rbp+18h]
0000000000503DF7 jmp 0000000000503DFC
0000000000503DFC leave
0000000000503DFD ret
似乎 TCC 期望整数寄存器 r6 到 r8 中的参数,而 msvc 将它们放在 sse 寄存器中。我认为 x64(在 Windows 上)定义了一种常见的调用约定?这里到底发生了什么,我如何在两个平台上执行相同的模型?
相同的代码在 32 位模式下也能正常工作。奇怪的是,在 OSX(其他代码由 llvm 编译)上,它可以在两种模式(32 位和 64 位)下工作。稍后我会看看我是否可以从那里获取一些组件。
- - 编辑 - -
我创建了一个可行的解决方案。然而,毫无疑问,这是我做过的最肮脏的 hack(禁止有问题的内联汇编,不幸的是它在 msvc 64 位上不可用:))。
// passes first three floating point arguments in r6 to r8
template<typename sseType>
sseType TCCAssemblyHelper(ScaleFunc cb, sseType val, sseType _min, sseType _max)
{
sseType xmm0(val), xmm1(_min), xmm2(_max);
long long rcx, rdx, r8;
rcx = *(long long*)&xmm0;
rdx = *(long long*)&xmm1;
r8 = *(long long*)&xmm2;
typedef float(*interMedFunc)(long long rcx, long long rdx, long long r8);
interMedFunc helperFunc = reinterpret_cast<interMedFunc>(cb);
return helperFunc(rcx, rdx, r8);
}