为什么GCC不编译这段代码?

时间:2013-08-07 11:07:59

标签: c++

我是一名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

5 个答案:

答案 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)

__尝试是SEH的事情。查看之前的问题herehere
我认为windows需要#include <excpt.h>
“首次使用”消息意味着这是您第一次使用它。
<{1}}和try与链接解释不同。

答案 2 :(得分:1)

符号__try__except未声明,编译器无法解析它们。
您应该阅读编译器关于此类关键字用法的文档(如果它们完全退出) 为此,C ++会为您提供trycatch个关键字,请尝试

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)

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

定义__try

定义__except

嘿presto工作。我运行的代码需要另一个';'据报道,这是有效的。

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