在 x86 平台中使用 -mcmodel=kernel 标志

Posted

技术标签:

【中文标题】在 x86 平台中使用 -mcmodel=kernel 标志【英文标题】:use of -mcmodel=kernel flag in x86 platform 【发布时间】:2018-08-29 02:04:18 【问题描述】:

我正在尝试将针对 x86 架构构建的设备驱动程序交叉编译到 arm 平台。它编译时没有任何错误,但我不认为所有功能都可用。所以我检查了makefile并找到了这个特定的部分。

ifeq ($(ARCH),x86_64)
    EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone

这似乎是唯一依赖于架构的部分。在谷歌上一段时间后,我发现 -mcmodel=kernel 用于内核代码模型,而 -mno-red-zone 是为了避免在内存中使用红色区域,它们都是针对 x86_64 的。但我不清楚,它将 cmodel 设置为内核有什么影响?

(非常感谢您对 arm 问题的任何见解。)

【问题讨论】:

【参考方案1】:

The x86 Options section of the GCC manual 说:

-mcmodel=kernel

为内核代码模型生成代码。 内核在负 2 GB 地址空间中运行。

(即上面的2GiB,地址如0xfffffffff0001234

在内核代码模型中,静态符号地址不适合 32 位零扩展常量(与默认小代码模型不同,其中 mov eax, imm32(5 字节)是放置符号地址的最有效方式一个寄存器)。

但它们确实适合符号扩展的 32 位常量,这与 large 代码模型不同。所以mov rax, sign_extended_imm32(7 字节)可以工作,大小相同,但可能比lea rax, [rel symbol] 效率稍高。

但更重要的是mov eax, [table + rdi*4] 有效,因为 disp32 位移符号扩展为 64 位。 -mcmodel=kernel 告诉 gcc 它可以做到这一点,但 mov eax, table 不能做到这一点


RIP 相对寻址也可以从任何代码地址(具有 rel32 +-2GiB 偏移量)到达任何符号,因此 -fPIC-fPIE 也将使您的代码工作,但代价是不利用在有用的情况下使用 32 位绝对寻址。 (例如索引静态数组)。

如果在没有-mcmodel=kernel (like these) 的情况下没有出现链接错误,则可能是a gcc that makes PIE executables by default(在最近的发行版中很常见),因此它避免了绝对寻址。

【讨论】:

以上是关于在 x86 平台中使用 -mcmodel=kernel 标志的主要内容,如果未能解决你的问题,请参考以下文章

SylixOS在x86平台的快速构建

x86平台转x64平台关于内联汇编不再支持的解决

VB.NET 为 x86 平台编译的应用程序设置不会在 Windows XP/Vista 32 位上运行

将 x86 转换为 x64 发生链接错误(2019)

如何正确建立和指定的配置和平台,x64和x86

使用带有 Web 平台安装程序 API 的 Powershell 仅在 64 位机器上获取 x86 安装程序