在 x86 中获取 Segment Override 前缀的 GCC 编译器选项是什么

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

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

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

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

据我所知,数据段(#DS)选择器将用于任何与数据相关的编译器代码。

因此数据部分(4k-8k)对于所有操作默认都会有#DS。除了一些可能使用 ES 的 str 操作。喜欢:

mov    $0xc00,%eax
addl   $0xd, (%eax)

但是,我想使用 Extra Segment(#ES) 选择器进行 CustomData 访问。我将为具有不同 Base 和 Limit 的 ES 定义一个新的 GDT 条目。 喜欢:

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

所以我的问题是:

GCC 是否有任何 x86 编译器标志,可用于告诉编译器使用 #ES 进行 CustomData 部分代码访问。?

意味着编译器标志将使用 #ES 为 CustomData 部分生成代码。?

提前致谢!

gcc x86 linker
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.