2

我是一名试图摆弄 C++ 的 Java、Python 程序员。我有以下代码片段 -

#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) __except' 未声明(首先使用此函数)

那条模糊的信息甚至意味着什么?因为 try 未声明我应该先尝试使用它?

编辑:

IDE -Codeblocks

编译器 -GCC

4

5 回答 5

7

此代码依赖于 Microsoft 的特定功能__try__except. 没有其他方法可以解决这个问题,因为IN在 Windows 中执行用户模式进程的指令通常会失败。在 VMWare 中,任何此类操作都会被 VMWare VMM(虚拟机监视器,有时也称为 Hypervisor)拦截。然后它检查一些寄存器中的特殊值并“接受”带有新值的指令,ebx以表明“是的,我是一个 VMWare 系统”。如果你在一个普通的旧 Windows 系统上运行它,它会因为尝试使用应用程序不可用的 IO 端口而得到一般保护错误 [通常,IO 端口对用户模式应用程序不可用代码]。

您需要使用 Microsoft 编译器编译它(并设置合适的“启用异常处理”标志 - 抱歉,不记得那个标志是什么,但它会告诉你它是否不正确)。GCC 不支持此功能。

但是,您可以使用 CPUID 指令而不是使用IN. 这在 GCC 编译器中会更好地工作,因为如果没有 VM 存在,它不会使处理器出错[对于学究:只要处理器晚于 1990 年代的某些 486 版本]。相反,它不会在寄存器中给出正确的值(不会更改寄存器值)。您可能需要编写一个cpuid内联汇编函数,但这不应该太难用谷歌搜索。

请参阅 VMware 网站上的此知识库文章: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 上使用过类似的东西,所以它可能不起作用)

于 2013-08-07T11:29:18.847 回答
5

__try 是 SEH 的事情。请在此处此处 查看以前的问题
我认为您需要#include <excpt.h>windows
“首次使用”消息意味着这是您第一次使用它。
try并且catch与链接解释的不同。

于 2013-08-07T11:13:01.020 回答
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的小文章。

于 2013-08-07T11:11:35.263 回答
1

C++ 异常不是使用 try{}catch{} 块吗?参考http://www.cplusplus.com/doc/tutorial/exceptions/

如果您使用 __try,您的 C++ 编译器可能会认为它是一个函数,因此会出现错误消息。

或者你可以做#define __try 试试宏!:)

另外,您使用的是什么编译器?如果您使用的是 GCC,我认为您可能还需要修复内联汇编的 clobberlist 以确保 GCC 不会过度优化它。

于 2013-08-07T11:12:12.077 回答
-2

我不是编码员,但我只是通过在调用它们之前定义它们来解决这个问题。

定义__try

定义 __except

嘿presto工作。我正在运行的代码需要另一个';' 据报道,补充说它有效。

希望这会有所帮助,因为我没有看到其他任何东西。:)

于 2017-09-18T22:15:06.337 回答