Question

How to prepare stack pointer for bare metal Rust?

I'm trying to write an x86 bootloader and operating system completely in Rust (no separate assembly files, only inline assembly within Rust).

My bootloader works completely as intended within the QEMU emulator, I'm far into the development of my kernel and my bootloader has never failed. I'm just worried if my bootloader has any undefined behavior and this behavior just happens to work for me.

One of the first "bootloader" things I need to do is set the stack pointer to a valid area of memory to act as my bootloader's stack. My bootloader uses local variables, and also sets the stack pointer with inline assembly.

// extreme oversimplification of what I have as my bootloader

#![no_std]
#![no_main]

#[no_mangle]
fn entry() -> !
{
    // place the stack area just before the boot sector
    unsafe { core::arch::asm!
    (
        "mov sp, 0x7c00"
    )}

    let bootloader_variable_1 = ...;
    let bootloader_variable_2 = ...;
    // do things with bootloader variables
}

My main concern is that the compiler allocates some space for local variables on the stack before anything within my entry function is ran and the compiler expects these variables to be at specific offsets, but then I manually change the stack pointer, invalidating all of the offsets.

Looking at the disassembly (x86 Intex syntax) of the generated binary when built in release mode, I see...

push bx
sub sp, 12

mov sp, 0x7c00
...

The generated assembly runs two commands before my function, both of which edit the stack pointer, and then I overwrite it. I'm surprised there haven't been any problems up to this point.

I'm not the most fluent in x86 assembly, but it seems like all instances of local variables are being optimized away from the stack and are used in processor registers instead, which is my best guess on why my bootloader works right now.

Is this cause for concern? Can I safely set the stack pointer in a no_std environment (at the very start of the program) and not corrupt any local variables? Will this scheme work on any and all Rust-compliant compilers? If not, is there any way to do this without some external assembly file?

I excluded my full bootloader stage 1 code and the full disassembly, but I can add it if anyone thinks it could help.

 22  1518  22
1 Jan 1970