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

在clang-cl中确保自定义ASM函数的x64合规性

问题:x64静态库内联汇编缺失Shadow Space的解决方法

我为自定义编译的原生x64 JIT代码实现了一些固有函数,多数由自研编译器生成,部分需被C++代码直接调用,因此希望将这些函数编译进静态库以支持静态链接甚至内联。

由于这些函数需要执行常规C++无法表达的操作(如通过函数输入设置非易失性寄存器),必须使用内联汇编。但函数本身需表现得像标准x64函数:具备序言/尾声,且拥有支持堆栈追踪和异常处理的必要unwind信息。因此我放弃原生编译器MSVC,转而在Visual Studio中用clang-cl编译静态库,当前实现代码如下:

void interruptEntry(void* pState, const char* pAddress)
{
    __asm
    {
        // load state into RBX
        mov rbx,rcx
        // load callstack-top into RDI
        mov rax,[rbx]
        mov rdi,[rax]

        // call address
        call rdx
    };
}

这段代码能生成正确的序言、尾声及所需unwind信息,但关键缺失x64要求的32字节shadow space(pAddress调用依赖该空间),生成的汇编代码如下:

Acclimate Engine.dll!interruptEntry(void *, const char *):
 push        rdi  
 push        rbx  
 mov         rbx,rcx  
 mov         rax,qword ptr [rbx]  
 mov         rdi,qword ptr [rax]  
 call        rdx  
 pop         rbx  
 pop         rdi  
 ret  

注意:代码由clang-cl生成,但DLL通过MSVC链接,静态库以O2优化编译。

我已尝试的方案:

  • 手动修改RSP(sub RSP,32):编译器会将其视为动态栈分配,建立帧指针,开销过大;
  • 在汇编中直接引用pState(mov rbx,pState):虽会添加shadow space,但pState会被复制到栈中再加载,违背初衷;
  • 在汇编块后直接调用pAddress函数指针:代码生成无变化;
  • 结合asm()/扩展asm与__attribute__((naked)):需手动编写序言/尾声,但clang-cl不识别.allocstack、.pushreg等unwind数据指令,报错“unknown directive”。

请问shadow space缺失的原因是什么?有无方法在不添加帧指针这类额外开销的前提下生成shadow space,同时保留unwind信息?也欢迎其他建议,比如是否存在可直接设置指定寄存器的固有函数(编译后仅对应一条mov指令),这样我就无需使用汇编(操纵具有全局影响的特定寄存器是无法用纯C++实现的核心原因)。

内容的提问来源于stack exchange,提问作者Juliean

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:12:52