我是一名Java,Python程序员,试图摆弄C ++。我有以下代码段 -
#include <windows.h>
bool IsInsideVMWare()
{
bool rc = true;
__try
{
__asm
{
push edx
push ecx
push ebx
mov eax, 'VMXh'
mov ebx, 0 // any value but not the MAGIC VALUE
mov ecx, 10 // get VMWare version
mov edx, 'VX' // port number
in eax, dx // read port
// on return EAX returns the VERSION
cmp ebx, 'VMXh' // is it a reply from VMWare?
setz [rc] // set return value
pop ebx
pop ecx
pop edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
rc = false;
}
return rc;
}
我遇到编译错误 -
__try' undeclared (first use this function)
__除了'未声明(首先使用此功能)
这种模糊的信息甚至意味着什么?因为try是未声明的,我应该先尝试使用它?
修改
IDE - Codeblocks
编译器 - GCC
答案 0 :(得分:6)
此代码依赖于__try
和__except
的Microsoft特定功能。没有其他方法可以解决这个问题,因为从Windows中的用户模式进程执行IN
指令通常会失败。在VMWare中,任何此类操作都被VMWare VMM(虚拟机监视器,有时也称为Hypervisor)拦截。然后它检查某些寄存器中的特殊值,并用ebx
中的新值“接受”该指令,以指示“是的,我是VMWare系统”。如果在普通的旧Windows系统上运行此操作,则会因尝试使用应用程序无法使用的IO端口而出现常规保护错误[通常,IO端口无法用于用户模式应用程序码]。
你需要使用Microsoft编译器编译它(并且设置了合适的“启用异常处理”标志 - 抱歉,不记得那个标志是什么,但是它会告诉你它是否不正确它是错误的)。 GCC不支持此功能。
但是,您可以使用CPUID指令而不是IN
来测试VMWare。这在GCC编译器中可以更好地工作,因为如果没有VM存在,它将不会使处理器出错[对于学员:只要处理器晚于1990年代的某个版本的486]。相反,它不会在寄存器中给出正确的值(不改变寄存器值)。您可能需要编写cpuid
内联汇编程序函数,但这不应该太难以谷歌了。
在VMware网站上查看此KB文章: http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458
或者,如果您真的坚持使用Windows结构化异常处理,您可以自己动手:
push handler // Save address of your handler.
push fs:[0] // Save address of any previous handler
mov fs:[0], esp // Save pointer to current exception record.
... // all the stuff setting registers, doing IN, etc.
jmp cleanup
handler:
mov [rc], 0 // Set "rc= false".
cleanup:
pop fs:[0]
add esp, 4 // Remove handler
(注意,我只是通过一些谷歌搜索来写的 - 自从我在Windows上使用类似的东西以来,这是一段时间,所以它可能无法正常工作)
答案 1 :(得分:5)
答案 2 :(得分:1)
符号__try
和__except
未声明,编译器无法解析它们。
您应该阅读编译器关于此类关键字用法的文档(如果它们完全退出)
为此,C ++会为您提供try
和catch
个关键字,请尝试
bool IsInsideVMWare()
{
bool rc = true;
try
{
__asm
{
...
}
}
catch(...) //catch all possible exceptions
{
rc = false;
}
return rc;
}
但请记住,C ++没有像Python或Java那样的深度运行时!因此只有少数运行时异常。
来自MSDN的小文章。
答案 3 :(得分:1)
C ++异常不是使用try {} catch {}块吗? 请参阅http://www.cplusplus.com/doc/tutorial/exceptions/
如果你使用__try,你的C ++编译器可能会认为它是一个函数,因此错误信息。
或者你可以做#define __try尝试使用宏! :)
另外,您使用的编译器是什么? 如果您正在使用GCC,我认为您可能还需要修复内联汇编的clobberlist,以确保GCC不会过度优化它。
答案 4 :(得分:-2)
我不是编码员,但我只是通过在调用它们之前定义它们来解决这个问题。
希望这会有所帮助,因为我没有看到其他任何事情。 :)