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

时间:2018-03-20 09:58:52

标签: c gcc makefile x86-64 red-zone

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

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

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

(对手臂问题的任何见解也非常感谢。)

1 个答案:

答案 0 :(得分:3)

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=kernellike these)的情况下没有收到链接错误,那么您可能会a gcc that makes PIE executables by default(在最近的发行版中很常见),因此它可以避免绝对寻址。