根据Visual Studio程序配置调用__readfsword()和__readgsword()

问题描述 投票:0回答:1

嗨,我是 Visual Studio 新手,

我想使用 Windows 固有的

__readfsword()
__readgsword()
,但我只能对 x86 使用
__readfsword()
,对 64 位应用程序使用
__readgsword()
。我正在为 x86 和 64 位应用程序构建我的程序。

如果我将应用程序配置更改为 x86,则会抛出错误,指出

__readgsword()
是无效标识符,但它会识别
__readfsword()
并针对 64 位进行反向操作。

我想在不更改应用程序的情况下构建我的应用程序,但由于此错误,我每次更改配置时都必须更改代码。 Visual Studio 中是否有一个解决方案,我可以在不更改代码的情况下进行构建,并且它根据配置使用这些功能?

c++ c windows visual-studio winapi
1个回答
0
投票

这个问题可以通过应用条件编译来解决。它是 C 和 C++ 的一项语言功能,允许根据编译时谓词包含或排除要编译的代码区域。

MSVC 提供了几个可用于派生谓词的预定义宏。有很多可供选择,挑战是选择最合适的。

这里的下意识反应是选择

_WIN32
_WIN64
。由于以下两个原因,这是不合适的:

  • 尽管它们看起来非常相似,但
    _WIN32
    _WIN64
    指的是不相关的概念:
    _WIN32
    描述了正在使用的API(即Win32子系统的API),而
    _WIN64
    是在针对64位时设置的-bit 版本的 Windows1.
  • 更重要的是,相关代码尝试使用仅在特定(系列)CPU 架构上可用的 CPU 指令。

因此,要使用的正确预定义宏是那些描述目标架构的宏,通常具有

_M
前缀(“机器”的缩写),即
_M_X64
2
_M_IX86

涵盖了基本原则,以下是可能的实现:

#include <intrin.h>

unsigned short read_word(unsigned long offset) {
    #if defined(_M_X64) && !defined(_M_ARM64EC)
        return __readgsword(offset);
    #elif defined(_M_IX86)
        return __readfsword(offset);
    #else
        #error "Unsupported architecture"
    #endif
}

这使编译器根据(编译器提供的)目标体系结构宏发出适当的代码。如果没有谓词匹配,则当编译器遇到

#error
指令时,编译将停止。

所有条件都在编译时严格评估,生成的目标代码是无分支的。

#error
情况也在编译时处理,通过继续或终止编译。


1 这样做的结果是,64 位应用程序项目通常同时定义了

_WIN32
_WIN64
,并且
#if defined(_WIN32)
并不意味着针对 32 位版本的 Windows。

2

_M_X64
也适用于
_M_ARM64EC
目标,其中“EC”是“仿真兼容”的缩写。我不知道内在函数是否是该模拟的一部分,因此条件排除
_M_ARM64EC

© www.soinside.com 2019 - 2024. All rights reserved.