mbr 中的堆栈初始化

stack initialization in mbr

假设我正在编写自己的 mbr 部分并且我想 运行 一些 C 代码。为此,我需要首先初始化堆栈,然后调用 C 代码。我以这样的方式做到了

boot.S 文件:

.code16

.section .bootstrap_stack #initializing stack here
stack_bottom:
.skip 16384
stack_top:

.text
.global _start
_start:
    cli
    movl $stack_top, %esp
    call kmain
loop:
    jmp loop

在我的 C 代码中我有函数 kmain

我的 linker.ld 文件如下所示:

OUTPUT_FORMAT(binary)
OUTPUT_ARCH(i8086)
ENTRY(_start)

SECTIONS
{
    . = 0x7C00;
    .text : { *(.text) }
    .sig : AT(0x7DFE)
    {
        SHORT(0xaa55);
    }
}

所以问题是内存部分 .bootstrap_stack 放在哪里?我没有告诉链接器脚本任何有关它的信息。但如果我这样做,那么输出文件的大小超过 512 字节,我不能将它用作 mbr。为什么在这个 C 堆栈正常工作之后?

如果你使用 ld 的 -M 选项来生成映射文件,你会看到它将地址 0 分配给 .bootstrap_stack:

Name             Origin             Length             Attributes
*default*        0x0000000000000000 0xffffffffffffffff

Linker script and memory map

                0x0000000000007c00                . = 0x7c00

.text           0x0000000000007c00        0x9
 *(.text)
 .text          0x0000000000007c00        0x9 t95.o
                0x0000000000007c00                _start

.sig            0x0000000000007c09        0x2 load address 0x0000000000007dfe
                0x0000000000007c09        0x2 SHORT 0xaa55
LOAD t95.o
OUTPUT(a.out binary)

.data           0x0000000000007c0b        0x0 load address 0x0000000000007e00
 .data          0x0000000000007c0b        0x0 t95.o

.bss            0x0000000000007c0b        0x0 load address 0x0000000000007e00
 .bss           0x0000000000007c0b        0x0 t95.o

.bootstrap_stack
                0x0000000000000000     0x4000
 .bootstrap_stack
                0x0000000000000000     0x4000 t95.o

您可以通过反汇编生成的二进制文件来验证这一点:

$ objdump -b binary -m i8086 --adjust-vma=0x7c00 -D a.out
...
    7c00:       fa                      cli
    7c01:       66 bc 00 40 00 00       mov    [=11=]x4000,%esp
    7c07:       eb fe                   jmp    0x7c07
        ...
    7dfd:       00 55 aa                add    %dl,-0x56(%di)

我建议使用您知道安全的固定常量加载 SP(而非 ESP),而不是使用实际上不会出现在生成的输出中的部分。同时还需要加载SS,因为栈的实际地址是SS:SP,也就是位于SS * 16 + SP。例如:

_start:
     xor %ax, %ax
     mov %ax, %ds
     mov %ax, %es
     mov %ax, %ss
     mov [=12=]x7c00, %sp  # stack grows downwards from start of boot loader