基于预处理器宏的代码产生 C2400 错误
#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:“{”:缺少函数 标题(旧式正式列表?)错误 C2014:预处理器命令必须启动 作为第一个非空白
#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] \
} \
}
Using the above macro causes the compiler to throw this error:
error C2400: inline assembler syntax
error in 'second operand'; found
'RESTORE'
What have I done incorrectly ?
EDIT:
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] \
}
The above code doesn't work either:
error C2447: '{' : missing function
header (old-style formal list?) error
C2014: preprocessor command must start
as first nonwhite space
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
至少我上次尝试时,无法在 VC++ 中的内联汇编块内创建标签。不过,使用 C 样式标签是可行的:
我已经有一段时间没有在 VC++ 中编写任何内联汇编了,所以我不能保证它会起作用,但我猜有一个相当公平的机会。
At least the last time I tried it, you couldn't create labels inside an inline assembly block in VC++. Using C-style labels works though:
I haven't written any inline assembly in VC++ for quite a while, so I can't guarantee that will work, but I'd guess there's a pretty fair chance.
我一直无法访问计算机,所以希望您已经解决了这个问题。我认为问题在于使用“\”结束该行实际上告诉 C 预处理器将下一行与该行合并。参见本页的评论3,以及线路拼接此处。这对于大多数 C 语句来说都可以,但对于汇编来说问题更大,因为新行是它定义语句的方式。
我可以想到两种解决方案。首先是找到类似C的“;”的东西可以用作汇编中的语句分隔符,我不知道是否存在这样的东西。第二种方法是将所有内容包装在单独的 __asm 语句中。采用第二种方法,您会得到以下结果:
注意:我已将标签留在 asm 语句之外,因为:
__asm
块中定义的标签的作用域规则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, and line splicing here. That works OK for most C statements, but is more problematic for assembly, since new lines are how it deliniates statements.
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
statements. Taking the second approach you get, the following:NOTE: I've left the labels outside of asm statements because:
__asm
blocks只是一个大胆的猜测:该宏会将所有文本扩展为一行,以
add esp, [k...] jz RESTORE jmp k...
结尾。也许在每个汇编指令末尾加一个分号会有所帮助。该假设的一个迹象是错误发生在您的第二“行”上。第一个是可以的,但是第二个将合并到第一个,所以这是编译器第一次感到困惑的机会。如果错误发生在稍后的某个地方,那么可能就不是这个了。
Just a wild guess: The macro will expand all the text to a single line, ending up with
add esp, [k...] jz RESTORE jmp k...
. Maybe it helps to put a semicolon at the end of each assembler instruction.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.
通过将函数体包含在另一个作用域中来修复它。
Fixed it by enclosing the function body in another scope.