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

启用C++替代运算符致MSVC内联汇编编译错误的解决办法

这个问题的根源其实是<ciso646>头文件的宏定义和MSVC内联汇编的指令名冲突了——<ciso646>会把and、or这些词预定义成&&、||的宏,而MSVC处理内联汇编时会先过一遍C++预处理器,导致汇编里的and被替换成&&,自然触发语法错误。

下面给你几个不用把汇编指令全大写的解决办法,按推荐程度排序:

1. 用#pragma push_macro/pop_macro临时管理宏定义(最推荐)

这个方法既解决汇编的冲突问题,又不会破坏代码其他地方对<ciso646>替代运算符的使用,安全性最高。原理是先保存当前and/or的宏定义,临时取消它们,写完汇编后再恢复。

修改你的示例代码如下:

__declspec (naked) Unit* __fastcall D2CLIENT_GetClientUnit(int nGUID, DWORD dwType) {
    // 临时保存并取消and/or的宏定义
    #pragma push_macro("and")
    #undef and
    #pragma push_macro("or")
    #undef or

    __asm {
        push edx
        mov eax, ecx
        shl edx, 0x09
        and eax, 0x7F
        add edx, [D2CLIENT_6FBBA608]
        call D2CLIENT_6FB54E20
        retn
    }

    // 恢复宏定义,不影响后续代码使用替代运算符
    #pragma pop_macro("or")
    #pragma pop_macro("and")
}

2. 仅在需要的代码块中使用<ciso646>

如果你的项目里只有部分代码需要用and/or这些替代运算符,不要全局包含<ciso646>,只在特定的源文件或函数里包含它。这样汇编所在的文件/函数不包含这个头,自然就不会有宏冲突问题。

比如:

// 仅在这个函数里用替代运算符
#include <ciso646>
void someFunction() {
    bool a = true and false; // 正常使用替代运算符
}

// 汇编所在的函数不包含<ciso646>
__declspec (naked) Unit* __fastcall D2CLIENT_GetClientUnit(int nGUID, DWORD dwType) {
    __asm {
        // 汇编指令正常写小写and/or,无冲突
        push edx
        mov eax, ecx
        shl edx, 0x09
        and eax, 0x7F
        add edx, [D2CLIENT_6FBBA608]
        call D2CLIENT_6FB54E20
        retn
    }
}

3. 将汇编指令写成字符串形式

MSVC的__asm支持用字符串来编写汇编代码,而预处理器不会处理字符串内部的内容,所以and/or不会被替换成宏。这种方法适合不想改动宏定义的场景,只是可读性稍差一点:

__declspec (naked) Unit* __fastcall D2CLIENT_GetClientUnit(int nGUID, DWORD dwType) {
    __asm {
        "push edx\n"
        "mov eax, ecx\n"
        "shl edx, 0x09\n"
        "and eax, 0x7F\n"
        "add edx, [D2CLIENT_6FBBA608]\n"
        "call D2CLIENT_6FB54E20\n"
        "retn"
    }
}

注意每个汇编行末尾要加\n来分隔指令,确保汇编器能正确解析。

4. 局部取消宏定义(简单但需注意影响范围)

如果汇编函数之后不需要使用and/or替代运算符,可以直接在汇编前#undef掉这两个宏:

__declspec (naked) Unit* __fastcall D2CLIENT_GetClientUnit(int nGUID, DWORD dwType) {
    #undef and
    #undef or

    __asm {
        push edx
        mov eax, ecx
        shl edx, 0x09
        and eax, 0x7F
        add edx, [D2CLIENT_6FBBA608]
        call D2CLIENT_6FB54E20
        retn
    }
}

这个方法简单,但如果后续代码还需要用替代运算符,就会失效,所以不如第一种方法安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:33:14