我有一个奇怪的错误。我有一个由一个编译器编译的模块(在本例中为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位)。我会看看我是否可以从那里取一些装配件。
----编辑----
我创建了一个有效的解决方案。然而,毫无疑问,这是我曾经做过的最脏的黑客攻击(可疑的内联汇编,不幸的是它在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);
}