Assembly 在简单内核的上下文中理解链接器脚本值

Assembly 在简单内核的上下文中理解链接器脚本值,assembly,x86,ld,linker-scripts,multiboot,Assembly,X86,Ld,Linker Scripts,Multiboot,关于开发一个小内核,我遵循这本书: 我已经到了必须链接二进制文件的地步,我想确保在继续之前理解链接器脚本: ENTRY(loader) /* the name of the entry label */ SECTIONS { . = 0x00100000; /* the code should be loaded at 1 MB */ .text ALIGN (0x1000) : /* align at 4 KB */

关于开发一个小内核,我遵循这本书:

我已经到了必须链接二进制文件的地步,我想确保在继续之前理解链接器脚本:

ENTRY(loader)                /* the name of the entry label */
SECTIONS {
    . = 0x00100000;          /* the code should be loaded at 1 MB */
    .text ALIGN (0x1000) :   /* align at 4 KB */
    {
        *(.text)             /* all text sections from all files */
    }
    .rodata ALIGN (0x1000) : /* align at 4 KB */
    {
        *(.rodata*)          /* all read-only data sections from all files */
    }
    .data ALIGN (0x1000) :   /* align at 4 KB */
    {
        *(.data)             /* all data sections from all files */
    }
    .bss ALIGN (0x1000) :    /* align at 4 KB */
    {
        *(COMMON)            /* all COMMON sections from all files */
        *(.bss)              /* all bss sections from all files */
    }
}
首先,为什么特定的
对齐
部分(4KB)?
(我认为这不太可能与优化有关,或者我可能弄错了,这可能是出于性能原因,因为否则我认为引导过程没有限制-通过删除脚本中的
ALIGN
函数调用确认)

然后考虑要链接的可执行文件:

 global loader                   ; the entry symbol for ELF

    MAGIC_NUMBER equ 0x1BADB002     ; define the magic number constant
    FLAGS        equ 0x0            ; multiboot flags
    CHECKSUM     equ -MAGIC_NUMBER  ; calculate the checksum
                                    ; (magic number + checksum + flags should equal 0)

    section .text:                  ; start of the text (code) section
    align 4                         ; the code must be 4 byte aligned
        dd MAGIC_NUMBER             ; write the magic number to the machine code,
        dd FLAGS                    ; the flags,
        dd CHECKSUM                 ; and the checksum

    loader:                         ; the loader label (defined as entry point in linker script)
        mov eax, 0xCAFEBABE         ; place the number 0xCAFEBABE in the register eax
    .loop:
        jmp .loop                   ; loop forever
我说的
.rodata
.bss
部分还不需要,对吗?(因为内核仍然可以正常启动)

从这个小小的链接器脚本中还有什么我无法从
ld
手册中理解的东西吗(我读了一些手册来理解点、
部分和入口点)


看起来我可以在脚本中重新安排部分的顺序,内核仍然可以工作,这是为什么?

在某些情况下,我认为如果在同一个4kb部分中有可写的数据段和代码,那么最终可能会导致缓存失效(性能问题)。如果您开始使用C或其他高级语言进行链接,您会发现数据放在
.rodata
中(通常是常量数据)
.bss
用于未初始化的数据或初始化为0的数据。通常,在执行依赖于它的代码执行之前,引导程序代码会希望显式地将零数据写入
.bss
部分。在C中,这通常是在调用
main
函数之前执行的C运行时代码中完成的。如果您刚开始编写汇编程序代码,那么这些可选部分中的许多部分都不适用,除非您自己创建它们(并且不要求有它们)。我不会只在汇编中执行,我尽可能多地使用C。如果您使用C,那么您几乎肯定要处理.bss。但是,如果您构建一个ELF二进制文件并使用多重引导,那么这实际上已经得到了解决。Grub将为您将
.bss
初始化为全零。您的标志设置为多引导0x0,表示ELF。您应该做的是创建一个引导堆栈(当grub加载时,您不能依赖于有一个有效的堆栈供您使用)。您可以在此处了解如何执行此操作:。您还需要使用
-ffreestanding-nostlib-lgcc
编译您的C代码(如果使用gcc),最后,如果您要使用C/C++请注意网站上关于使用交叉编译器生成内核的建议。您尤其需要一个
i686 elf gcc
交叉编译器。操作系统开发站点应该链接到构建操作系统的说明。如果您使用主机环境中的
gcc
,您可能会在生成的代码中发现一些小问题。这是因为编译器和C运行时将以主机环境为目标,而不是以基本环境为目标。相信我,你不想回来帮助我们找出由于使用错误的gcc而导致的错误