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

在x86平台中使用-mcmodel=kernel标志,c,gcc,makefile,x86-64,red-zone,C,Gcc,Makefile,X86 64,Red Zone,我正在尝试将一个为x86架构构建的设备驱动程序交叉编译到arm平台。它编译时没有任何错误,但我认为没有完整的功能可用。所以我检查了makefile并找到了这个特殊的部分 ifeq ($(ARCH),x86_64) EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone 这似乎是唯一依赖于架构的部分。在google上呆了一段时间后,我发现-mcmodel=kernel是用于内核代码模型的,-mno red zone是为了避免在内存中使用red zone

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

ifeq ($(ARCH),x86_64)
    EXTRA_CFLAGS += -mcmodel=kernel -mno-red-zone
这似乎是唯一依赖于架构的部分。在google上呆了一段时间后,我发现-mcmodel=kernel是用于内核代码模型的,-mno red zone是为了避免在内存中使用red zone,它们都是用于x86_64的。但我不清楚,将cmodel设置为内核会产生什么影响

(对arm问题的深入了解也非常感谢。)

说:

-mcmodel=kernel

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

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

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

但它们确实适合符号扩展的32位常量,例如,与
large
代码模型不同。所以
mov-rax,sign\u-extended\u-imm32(7字节)可以工作,大小相同,但可能比
lea-rax,[rel-symbol]
稍微有效

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


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

如果您在没有
-mcmodel=kernel
()的情况下没有收到链接错误,那么您可能已经收到了(在最近的发行版上很常见),因此它避免了绝对寻址。

说:

-mcmodel=kernel

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

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

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

但它们确实适合符号扩展的32位常量,例如,与
large
代码模型不同。所以
mov-rax,sign\u-extended\u-imm32(7字节)可以工作,大小相同,但可能比
lea-rax,[rel-symbol]
稍微有效

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


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

如果您在没有
-mcmodel=kernel
()的情况下没有得到链接错误,那么您可能已经得到了链接错误(在最近的发行版上很常见),因此它避免了绝对寻址