我正在尝试将为x86架构构建的设备驱动程序交叉编译为arm平台。它编译没有任何错误,但我不认为整个功能可用。所以我检查了makefile并找到了这个特殊的部分。
ifeq ($(ARCH),x86_64)
EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone
这是唯一依赖于架构的部分。在谷歌上一段时间后,我发现-mcmodel = kernel用于内核代码模型,-mno-red-zone用于避免在内存中使用红色区域,并且它们都用于x86_64。但是我不清楚,它将cmodel设置为内核有什么影响?
(对手臂问题的任何见解也非常感谢。)
答案 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=kernel
(like these)的情况下没有收到链接错误,那么您可能会a gcc that makes PIE executables by default(在最近的发行版中很常见),因此它可以避免绝对寻址。