Pass multiboot pointer as argument to rust_main

This commit is contained in:
Philipp Oppermann
2015-11-12 17:52:22 +01:00
parent d07530d660
commit 73aa41e25e
4 changed files with 24 additions and 2 deletions

View File

@@ -8,6 +8,25 @@ TODO
## The Multiboot Information Structure
When a Multiboot compliant bootloader loads a kernel, it passes a pointer to a boot information structure in the `ebx` register. We can use it to get information about available memory and loaded kernel sections.
First, we need to pass this pointer to our kernel as an argument to `rust_main`. To find out how arguments are passed to functions, we can look at the [calling convention of Linux]:
[calling convention of Linux]: https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI
> The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, and R9
So to pass the pointer to our kernel, we need to move it to `rdi` before calling the kernel. Since we're not using the `rdi`/`edi` register in our bootstrap code right now, we can simply set the `edi` register right after booting (in `boot.asm`):
```nasm
start:
mov esp, stack_top
mov edi, ebx ; Move Multiboot info pointer to edi
```
Now we can add the argument to our `rust_main`:
```rust
pub extern fn rust_main(multiboot_information_address: usize) { ... }
```
## Start and End of Kernel
We can now use the ELF section tag to calculate the start and end address of our loaded kernel:

View File

@@ -19,6 +19,9 @@ section .text
bits 32
start:
mov esp, stack_top
; Move Multiboot info pointer to edi to pass it to the kernel. We must not
; modify the `edi` register until the kernel it called.
mov edi, ebx
call test_multiboot
call test_cpuid

View File

@@ -20,7 +20,7 @@ bits 64
long_mode_start:
call setup_SSE
; call rust main
; call rust main (with multiboot pointer in rdi)
call rust_main
.os_returned:
; rust main returned, print `OS returned!`

View File

@@ -23,7 +23,7 @@ extern crate spin;
mod vga_buffer;
#[no_mangle]
pub extern fn rust_main() {
pub extern fn rust_main(multiboot_information_address: usize) {
// ATTENTION: we have a very small stack and no guard page
vga_buffer::clear_screen();
println!("Hello World{}", "!");