GCC 编译器选项可在 x86 中获取 ES 段覆盖前缀?

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

我有内存布局(在增加内存地址中),例如:

代码部分(0-4k),数据部分(4k-8k),堆栈部分(8k-12k),自定义数据部分(12k-16k)。

我在自定义数据部分放置了一些特殊的数组、结构。

据我所知,数据段(DS)选择器将用于任何与数据相关的编译器代码。
因此数据部分(4k-8k)对于所有操作默认都会有 DS。 (除了一些可能使用 ES 的 str 操作)。

例如,除了 EBP 和 ESP 之外的基址寄存器,默认段基址是 DS:

mov    $0xc00,%eax
addl   $0xd, (%eax)   # address is DS:EAX

但是,我想使用额外段(ES)选择器进行自定义数据访问。我将为具有不同 Base 和 Limit 的 ES 定义一个新的 GDT 条目。 所以我需要编译器像这样发出 asm:

mov    $0x3400,%eax
addl   $0xd, %es:(%eax)

GCC 是否有任何 x86 编译器标志,可用于告诉编译器使用

ES
段来访问特定部分中的变量,例如标有
__attribute__((section("CustomSection")))
?

的变量
gcc x86 linker memory-segmentation compiler-options
2个回答
0
投票

虽然问题要求提供一个选项,使 gcc 的代码生成使用 es 前缀来访问自定义部分,但如果您想以手写代码执行此操作,AT&T 语法已经允许例如%es:(%eax).

注意,这可能会破坏 gcc 有时内联的代表字符串指令; fs 或 gs 将是唯一明智的选择,即使在 x86-64 中仍然可用。

(根据 Peter Cordes 的有用批评制作此评论社区 wiki。)


0
投票

引用 clang 语言扩展文档中的示例

#define GS_RELATIVE __attribute__((address_space(256)))
int foo(int GS_RELATIVE *P) {
  return *P;
}

编译为(在 X86-32 上):

_foo:
        movl    4(%esp), %eax         # load the arg
        movl    %gs:(%eax), %eax      # use it with its prefix
        ret

地址空间 256 是

gs
,257 是
fs
,258 是
ss

文档没有提到

es
;编译器通常假设
es
=
ds
,因此如果他们根据调整选项选择这样做,他们可以自由地内联 memcpy / memset 的
rep movs
rep stos
memcpy
memset
的库实现也可能在某些CPU上使用rep stos/movs。 相关:为什么 std::fill(0) 比 std::fill(1) 慢?

显然这确实是低级的东西,只有当您已经设置了 GS 或 FS 基地址时才有意义。 (

wrfsbase
)。 请注意,i386 Linux 使用
gs
作为用户空间中的线程本地存储,而 x86-64 Linux 使用
fs


我不知道 gcc、ICC 或 MSVC 是否有此类扩展。

嗯,GNU C 中有

__thread
,它将根据目标平台使用
%gs:
%fs:
前缀。 gcc `__thread` 是如何工作的?.

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