You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编函数导致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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 16:35:09