代码之家  ›  专栏  ›  技术社区  ›  shadeMe

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

  •  0
  • shadeMe  · 技术社区  · 14 年前
    #define CANCEL_COMMON_DIALOG_HOOK(name)  \
    void __declspec(naked) ##name##CancelCommonDialogHook(void)  \
    {  \
        __asm  \
        {  \
            add     esp, [k##name##CancelCommonDialogStackOffset]  \
            jz      RESTORE  \
            jmp     [k##name##CancelCommonDialogNewFileRetnAddr]  \
        RESTORE:  \
            pushad  \
            call    DoSavePluginCommonDialogHook  \
            test    eax, eax  \
            jnz     REMOVE  \
            popad  \
            jmp     [k##name##CancelCommonDialogRestoreRetnAddr]  \
        REMOVE:  \
            popad  \
            jmp     [k##name##CancelCommonDialogRemoveRetnAddr]      \
        }  \
    }
    

    使用上述宏会导致编译器引发此错误:

    错误C2400:内联汇编程序语法 “第二个操作数”中有错误;找到 “还原”

    我做错了什么?

    编辑:

    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]          \
    }
    

    上述代码也不起作用:

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

    4 回复  |  直到 9 年前
        1
  •  0
  •   Jerry Coffin    14 年前

    至少在我上次尝试它时,您无法在VC++的内联程序集块内创建标签。但是,使用C样式标签是可行的:

    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]      \
        }  \
    }
    

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

        2
  •  0
  •   torak    14 年前

    I've been without computer access, so hopefully you've resolved this already. I think that the problem is that using "\" to end the line actually tells the C preprocessor to merge the next line with this line. See comment 3 on this page 和线路拼接 here . 这对于大多数C语句都可以,但对于汇编来说更为困难,因为新行是它如何删除语句的。

    I can think of two approaches to a solution. The first is to find something like C's ";" which can be used as a statment separator in assembly, I don't know if such a thing exists. The second approach is to wrap everything in separate __asm 声明。采用第二种方法,如下:

    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]}        \
    }
    

    注意:我将标签放在asm语句之外,因为:

    1. 我想你可以
    2. 我不确定中定义的标签范围规则 阿斯马 阻碍
        3
  •  0
  •   Roland Illig    14 年前

    只是一个疯狂的猜测:宏将把所有文本扩展到一行,以 add esp, [k...] jz RESTORE jmp k... . 也许在每个汇编程序指令的末尾放一个分号会有所帮助。

    An indication for that hypothesis is that the error occurs on your second "line". The first is ok, but the second will be merged to the first, so this is the first chance for the compiler to get confused. Had the error been somewhere later, this wouldn't be it probably.

        4
  •  0
  •   shadeMe    14 年前

    通过将函数体封闭在另一个范围中来修复它。