Gcc 将32位和64位代码链接到一个二进制文件中

Gcc 将32位和64位代码链接到一个二进制文件中,gcc,x86-64,osdev,binutils,Gcc,X86 64,Osdev,Binutils,在对这个问题的评论中,, , Michael Petch写道,“64位ELF格式支持32位代码段。” 我有一个工作程序,包括32位和64位代码以及它们之间的切换。我一直无法弄清楚如何在没有链接器错误的情况下将编译器生成的32位和64位代码链接在一起,所以所有32位代码都是在汇编中编写的。随着项目变得更加复杂,32位汇编代码的维护变得更加繁重 以下是我所拥有的: test32.cc是用-m32编译的 所有其他源文件在编译时都没有该标志,并且使用-mcmodel=kernel 在链接器脚本中: OU

在对这个问题的评论中,, , Michael Petch写道,“64位ELF格式支持32位代码段。”

我有一个工作程序,包括32位和64位代码以及它们之间的切换。我一直无法弄清楚如何在没有链接器错误的情况下将编译器生成的32位和64位代码链接在一起,所以所有32位代码都是在汇编中编写的。随着项目变得更加复杂,32位汇编代码的维护变得更加繁重

以下是我所拥有的:

test32.cc是用
-m32
编译的
所有其他源文件在编译时都没有该标志,并且使用
-mcmodel=kernel

在链接器脚本中:

OUTPUT_FORMAT("elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
在Makefile中:

LD := ld
LDFLAGS := -Map $(TARGET).map -n --script $(LDSCRIPT)
$(LD) $(LDFLAGS) -b elf32-x86-64 $(OBJS64) -b elf32-i386 $(OBJS32) -o $@
我得到一个错误:

ld: i386 architecture of input file 'test32.o' is incompatible with i386:x86-64 output
将输出更改为i386会导致所有64位对象模块出现类似错误

我正在使用:
通用条款5.4.1

GNU ld(用于Ubuntu的GNU Binutils)2.26.1

我说的是32位和64位部分,而不是32位和64位elf文件。您不能链接32位elf文件和64位elf文件。您可以使用elf64文件来包含32位和64位代码。通常,在这些OSDev问题中,32位/64位代码段位于汇编文件中,您可以(使用NASM)使用
位32
/
位64
.code32
/
code64
with AS)指令,但您仍然生成一个elf64对象。这是一个带有32位组件的64位操作系统吗?您正在查看多少32位汇编代码?什么类型的功能?我这样问是因为我想知道维护32位汇编代码有多么繁重。运行32位代码时,是否将处理器切换到长模式?或者所有的32位代码都是在进入长模式之前使用的,之后就不再使用了?我只是想知道,如果你从长模式切换到32位保护模式(然后又回到长模式),你运行的是哪种类型的代码,而这在长模式下是做不到的?通常,32位代码与进入长模式之前所做的事情隔离(是否使用GRUB?GRUB2?)。如果我了解代码的使用方式,我可能会给你一些想法。如果你使用多重引导,并且32位代码严格用于引导到长模式(包括设置分页等),那么我会将引导/多重引导代码构建为elf32可执行代码,然后将64位内核指定为模块(GRUB/mltiboot加载程序将按原样将模块读入内存中)。我要做的是编写一个简单的64位ELF解析器(您甚至不需要重新定位,从而简化了工作)。然后使用该ELF解析器将64位ELF文件(内核)放入内存中您需要的位置(如果使用分页功能,则更容易)。然后将控制转移到64位代码。这允许32位ELF可执行文件引导所有内容(大部分可以用C编写),加载64位ELF可执行文件并将控制转移到它。您也可以使用自定义引导加载程序(如果您不使用多引导加载程序)执行此操作。整个想法是将32位引导代码保存在32位ELF可执行文件中,将64位代码保存在ELF64可执行文件中。