汇编函数导致Visual Studio中调用栈无法正常识别的问题排查
调试x64汇编调用栈异常问题
我正在开发一款基于C的脚本语言VM,脚本函数可通过类似JNI的原生接口API回调原生函数。我制作了最小化演示示例,C测试代码如下:
float sum_values(void* env, int a, float b, int c, float d) { return static_cast<float>(a) + b + c + d; } extern "C" float native_call_amd64_msvc(void* env, void* function, uint64_t* args, size_t numArgs); int main() { uint64_t args[]{ 0x1111, 0, 0x3333, 0 }; *reinterpret_cast<float*>(args + 1) = 2.222f; *reinterpret_cast<float*>(args + 3) = 4.444f; const float result = native_call_amd64_msvc ( reinterpret_cast<void*>(0xDEADCAFEBABEA0BA), reinterpret_cast<void*>(sum_values), args, std::size(args) ); const float control_result = sum_values(nullptr, 0x1111, 2.222f, 0x3333, 4.444f); std::cout << ((result == control_result) ? "passed" : "failed") << std::endl; return 0; }
如代码所示,我分别通过脚本API和常规方式调用sum_values函数验证结果。由于需要最高灵活性,我无法使用模板或C可变参数转发脚本栈操作数,而是将参数存储在数组中,通过汇编编写的中间函数native_call_amd64_msvc(遵循x64调用约定)正确转发参数至原生栈帧,该汇编函数实现如下:
native_call_amd64_msvc PROC enter 0, 0 mov RBX, RDX ; duplicate the function pointer (MUL will overwrite RDX, also RDX may be used for an arg) mov RAX, 8 mul R9 add RAX, R8 ; RAX is now pointing to the arguments "tail" args_to_stack: cmp RAX, R8 je args_to_registers sub RAX, 8 push qword ptr [RAX] jmp args_to_stack args_to_registers: ; arguments are passed through [RCX (Env), RDX (1st arg), R8 (2nd arg), R9 (3rd arg)] push RCX cmp R9, 1 ; num args >= 1 jl invoke_function mov RDX, [RSP + (8 * 1)] movd XMM1, RDX ; here and below - also store arguments in XMM registers. may be redundant if the argument is not a float/double cmp R9, 2 ; num args >= 2 jl invoke_function mov R8, [RSP + (8 * 2)] movd XMM2, R8; cmp R9, 3 ; num args >= 3 jl invoke_function mov R9, [RSP + (8 * 3)] ; note: this overwrites the num_arg in r9, but we don't need it anymore movd XMM3, R9; invoke_function: call RBX leave ret native_call_amd64_msvc ENDP
功能运行完全正常,结果有效,但在Visual Studio中为sum_values设置断点调试时,调用栈显示异常;而常规调用时调用栈显示正常。我希望能正常调试代码,想了解哪里遗漏了,是否存在更大的疏漏。
内容的提问来源于stack exchange,提问作者Netherwire
相关产品推荐
相关产品推荐

