PepeHands
PepeHands

Reputation: 1406

stack initialization in mbr

Suppose I'm writing my own mbr section and I want to run some C code where. To do so I need firstly initialize stack and after that call C code. I did that in a way like this

boot.S file:

.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

In my C code I have function kmain.

My linker.ld file looks like this:

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

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

So the question is where in memory section .bootstrap_stack placed? I dont tell linker script anything about it. But if I do then the size of output file is more than 512 bytes and I can't use it as mbr. Why after this C stack works correctly?

Upvotes: 1

Views: 324

Answers (1)

Ross Ridge
Ross Ridge

Reputation: 39591

If you use the -M option of ld so that it produces a map file, you'll see that it assigns the address 0 to .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

You can verify this by disassembling generated binary:

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

Instead of using a section that won't actually appear in your generated output, I'd recommend loading SP (not ESP) with a fixed constant that you know is safe. You also need to load SS at the same time, as the actual address of the stack is SS:SP, that is, it's located at SS * 16 + SP. For example:

_start:
     xor %ax, %ax
     mov %ax, %ds
     mov %ax, %es
     mov %ax, %ss
     mov $0x7c00, %sp  # stack grows downwards from start of boot loader

Upvotes: 2

Related Questions