C++ 基于预处理器宏的代码产生C2400错误

C++ 基于预处理器宏的代码产生C2400错误,c++,visual-studio,assembly,c-preprocessor,C++,Visual Studio,Assembly,C Preprocessor,使用上述宏会导致编译器抛出此错误: 错误C2400:内联汇编程序语法 “第二个操作数”中有错误;建立 “恢复” 我做错了什么 编辑: 上述代码也不起作用: 错误C2447:“{”:缺少函数 标题(旧式正式列表?)错误 C2014:必须启动预处理器命令 作为第一个非空白 至少在我上次尝试它时,您无法在VC++中的内联汇编块中创建标签。不过,使用C样式标签也可以: void __declspec(naked) #name##CancelCommonDialogHook(void)

使用上述宏会导致编译器抛出此错误:

错误C2400:内联汇编程序语法 “第二个操作数”中有错误;建立 “恢复”

我做错了什么

编辑:

上述代码也不起作用:

错误C2447:“{”:缺少函数 标题(旧式正式列表?)错误 C2014:必须启动预处理器命令 作为第一个非空白


至少在我上次尝试它时,您无法在VC++中的内联汇编块中创建标签。不过,使用C样式标签也可以:

void __declspec(naked) #name##CancelCommonDialogHook(void)               \ 
{                                                                        \
    __asm   add     esp, [k##name##CancelCommonDialogStackOffset]        \
    __asm   jz      RESTORE                                              \
    __asm   jmp     [k##name##CancelCommonDialogNewFileRetnAddr]         \
    RESTORE:                                                             \
    __asm   pushad                                                       \
    __asm   call    DoSavePluginCommonDialogHook                         \
    __asm   test    eax, eax                                             \
    __asm   jnz     REMOVE                                               \
    __asm   popad                                                        \
    __asm   jmp     [k##name##CancelCommonDialogRestoreRetnAddr]         \
    REMOVE:                                                              \
    __asm   popad                                                        \
    __asm   jmp     [k##name##CancelCommonDialogRemoveRetnAddr]          \
}

我已经有很长一段时间没有用VC++编写任何内联程序集了,所以我不能保证它会工作,但我想这是一个相当公平的机会。

我一直没有计算机访问权限,所以希望你已经解决了这个问题。我想问题在于使用“\”结束这一行实际上是告诉C预处理器将下一行与这一行合并。请参阅上的注释3和行拼接。这对大多数C语句都适用,但对汇编来说问题更大,因为新行是它将语句解除的方式

我可以想出两种解决方案。第一种方法是找到像C“;”这样的东西,它可以在汇编中用作station分隔符,我不知道是否存在这样的东西。第二种方法是将所有内容包装在单独的
\u asm
语句中。采用第二种方法,您可以得到以下内容:

void __declspec(naked) ##name##CancelCommonDialogHook(void)  \
{  \
    __asm  \
    {  \
        add     esp, [k##name##CancelCommonDialogStackOffset]  \
        jz      RESTORE  \
        jmp     [k##name##CancelCommonDialogNewFileRetnAddr]  \
    }           \
    RESTORE:    \
    _asm {      \
        pushad  \
        call    DoSavePluginCommonDialogHook  \
        test    eax, eax  \
        jnz     REMOVE  \
        popad  \
        jmp     [k##name##CancelCommonDialogRestoreRetnAddr]  \
    }          \
    REMOVE:    \
    __asm {    \
        popad  \
        jmp     [k##name##CancelCommonDialogRemoveRetnAddr]      \
    }  \
}
注意:我将标签放在asm语句之外,因为:

  • 我想你可以
  • 我不确定
    \u asm
    块中定义的标签的范围规则

  • 胡乱猜测:宏将把所有文本扩展到一行,结果是
    add esp,[k..]jz RESTORE jmp k..
    。在每个汇编指令的末尾加上分号可能会有所帮助


    该假设的一个迹象是错误发生在你的第二行。第一个是可以的,但是第二个将合并到第一个,因此这是编译器第一次出现混淆的机会。如果错误发生在以后的某个地方,这可能不会是错误。

    通过将函数体包含在另一个作用域中来修复它。

    刚刚使用VS2010进行了测试,我能够创建没有任何问题的标签,并且似乎可以重新创建标签这可能已经有一段时间了。我明白了。我会尝试一下。编辑:嗯,不好。在其他新错误中,jz调用仍然会引发错误。我只是想澄清一下,我使用的是VS 2008。当你查看预处理器的结果时,有什么突出的地方吗?嗯,结果中似乎没有任何换行符。令牌粘贴操作符In第三行未被识别为一行-编译器认为它是一个指令。用修改过的代码编辑了问题。@shadeMe:您可以尝试从程序集中取出标记粘贴,改为使用函数指针。
    void __declspec(naked) ##name##CancelCommonDialogHook(void)  \
    {  \
        __asm  \
        {  \
            add     esp, [k##name##CancelCommonDialogStackOffset]  \
            jz      RESTORE  \
            jmp     [k##name##CancelCommonDialogNewFileRetnAddr]  \
        }           \
        RESTORE:    \
        _asm {      \
            pushad  \
            call    DoSavePluginCommonDialogHook  \
            test    eax, eax  \
            jnz     REMOVE  \
            popad  \
            jmp     [k##name##CancelCommonDialogRestoreRetnAddr]  \
        }          \
        REMOVE:    \
        __asm {    \
            popad  \
            jmp     [k##name##CancelCommonDialogRemoveRetnAddr]      \
        }  \
    }
    
    void __declspec(naked) ##name##CancelCommonDialogHook(void)          
    {                                                                    
        __asm{add     esp, [k##name##CancelCommonDialogStackOffset]}      \
        __asm{jz      RESTORE}                                            \
        __asm{jmp     [k##name##CancelCommonDialogNewFileRetnAddr]}       \
        RESTORE:                                                          \
        __asm{pushad}                                                     \
        __asm{call    DoSavePluginCommonDialogHook}                       \
        __asm{test    eax, eax}                                           \
        __asm{jnz     REMOVE}                                             \
        __asm{popad}                                                      \
        __asm{jmp     [k##name##CancelCommonDialogRestoreRetnAddr]}       \
        REMOVE:                                                           \
        __asm{popad}                                                      \
        __asm{jmp     [k##name##CancelCommonDialogRemoveRetnAddr]}        \
    }