X86 链接器和内核的困境

X86 链接器和内核的困境,x86,linker,g++,kernel,osdev,X86,Linker,G++,Kernel,Osdev,四天后我就撞到墙了。我和OSDev tut一起工作,已经找了两天了。我什么都试过了。首先,我意识到自己很愚蠢,我正在尝试64位编译,这就是为什么我得到了一个“.relocation截断以适应:rva32反对…”。我转到Cygwin32,现在我无法看到内核中的main 对不起,如果这是愚蠢的,我试图在课间做这件事,我被烧死了 boot.asm使用>>>nasm-f elf boot.asm-o boot.o编译 MBALIGN equ 1<<0

四天后我就撞到墙了。我和OSDev tut一起工作,已经找了两天了。我什么都试过了。首先,我意识到自己很愚蠢,我正在尝试64位编译,这就是为什么我得到了一个“.relocation截断以适应:rva32反对…”。我转到Cygwin32,现在我无法看到内核中的main

对不起,如果这是愚蠢的,我试图在课间做这件事,我被烧死了

boot.asm使用>>>nasm-f elf boot.asm-o boot.o编译

MBALIGN     equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MBALIGN | MEMINFO      ; this is the Multiboot 'flag' field
MAGIC       equ  0x1BADB002             ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum of above, to prove we are multiboot

section .multiboot
align 4
    dd MAGIC
    dd FLAGS
    dd CHECKSUM

section .bootstrap_stack
align 4
stack_bottom:
times 16384 db 0
stack_top:

section .text
global _start
_start:

    mov esp, stack_top

    call kernel_main

    cli
.hang:
    hlt
    jmp .hang

也许我只是被烧坏了,没有看到简单的东西,但这就是为什么我在这里的原因。默认情况下,GCC会将所谓的“启动文件”添加到您的对象文件中,使其无法启动。要禁用它们,请将
-nostartfiles
附加到
g++
的参数列表中。此外,C++需要一堆其他的东西,以便它甚至启动! 请参阅:

我知道这个问题比较老,但从遇到的问题中可以学到一些东西。假设是32位编译,会有一些问题,可能是一个gotchya导致了您的问题

链接时,您已指定.bootstrap_堆栈将放置在.bss部分:

boot.asm
中,您使用以下内容定义堆栈:

section .bootstrap_stack
align 4
stack_bottom:
    times 16384 db 0
stack_top:
这很好,但是您不应该尝试将初始化数据放入.bss,并且您确实添加的部分应该将
nobits
alloc
、和
write
属性设置为与典型的bss段兼容。它可能看起来像:

section .bootstrap_stack nobits alloc write
align 4
stack_bottom:
    resb 16384          ; Reserves but doesn't initialize 16384 bytes
stack_top:
nasm -f elf32 boot.asm -o boot.o
g++ -m32 -c kernel.cpp -o kernel.o -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti
g++ -m32  -Wl,--build-id=none -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib -fno-exceptions boot.o kernel.o -lgcc
进行这些更改将在BSS段中设置适当的堆栈(16k大小),并避免汇编程序和链接程序警告

boot.asm
中,您可以
调用kernel\u main
。这很好,但是因为它不在boot.asm中,所以应该告诉汇编程序(NASM)它是一个外部标签。在
boot.asm
的顶部,您应该添加:

extern kernel_main
使用GCC最大的潜在问题是,它会在ELF头之后放置一个4k节,其中包含
.note.gnu.build id
。这几乎可以保证您的
节.multiboot
将被放置在ELF二进制文件的8k点之外,并会导致multiboot加载程序(如GRUB)告诉您在文件中找不到multiboot头。为了解决这个问题,您需要将最终的内核二进制文件(
myos.bin
)与链接器选项
-Wl,--buildid=none
链接起来。您还应该明确告诉NASM使用
-f elf32
和带有
-m32
选项的GCC生成32位ELF对象。编译和链接命令的外观如下所示:

section .bootstrap_stack nobits alloc write
align 4
stack_bottom:
    resb 16384          ; Reserves but doesn't initialize 16384 bytes
stack_top:
nasm -f elf32 boot.asm -o boot.o
g++ -m32 -c kernel.cpp -o kernel.o -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti
g++ -m32  -Wl,--build-id=none -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib -fno-exceptions boot.o kernel.o -lgcc
要编译并链接调试符号,可以执行以下操作:

nasm -f elf32 -g -F dwarf boot.asm -o boot.o
g++ -g -m32  -c kernel.cpp -o kernel.o -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti
g++ -g -m32  -Wl,--build-id=none -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib -fno-exceptions boot.o kernel.o -lgcc
您还应该注意OSDev Wiki使用交叉编译器而不是根据您的主机环境定制的本机编译器进行构建的重要性。从长远来看,这可以避免一些难以发现的错误

修改后的
boot.asm
可能如下所示:

extern kernel_main

MBALIGN     equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MBALIGN | MEMINFO      ; this is the Multiboot 'flag' field
MAGIC       equ  0x1BADB002             ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum of above, to prove we are multiboot

section .multiboot
align 4
    dd MAGIC
    dd FLAGS
    dd CHECKSUM

section .bootstrap_stack nobits alloc write
align 4
stack_bottom:
    resb 16384               ; Reserves but doesn't initialize 16384 bytes
stack_top:

section .text
global _start
_start:

    mov esp, stack_top

    call kernel_main

    cli
.hang:
    hlt
    jmp .hang
extern内核\u main
姆巴林平等1
extern kernel_main

MBALIGN     equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MBALIGN | MEMINFO      ; this is the Multiboot 'flag' field
MAGIC       equ  0x1BADB002             ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum of above, to prove we are multiboot

section .multiboot
align 4
    dd MAGIC
    dd FLAGS
    dd CHECKSUM

section .bootstrap_stack nobits alloc write
align 4
stack_bottom:
    resb 16384               ; Reserves but doesn't initialize 16384 bytes
stack_top:

section .text
global _start
_start:

    mov esp, stack_top

    call kernel_main

    cli
.hang:
    hlt
    jmp .hang