C++ 基于预处理器宏的代码产生C2400错误
使用上述宏会导致编译器抛出此错误: 错误C2400:内联汇编程序语法 “第二个操作数”中有错误;建立 “恢复” 我做错了什么 编辑: 上述代码也不起作用: 错误C2447:“{”:缺少函数 标题(旧式正式列表?)错误 C2014:必须启动预处理器命令 作为第一个非空白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)
至少在我上次尝试它时,您无法在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]} \
}