mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 14:27:49 +00:00
Pass multiboot pointer as argument to rust_main
This commit is contained in:
@@ -8,6 +8,25 @@ TODO
|
|||||||
## The Multiboot Information Structure
|
## 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.
|
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
|
## Start and End of Kernel
|
||||||
We can now use the ELF section tag to calculate the start and end address of our loaded kernel:
|
We can now use the ELF section tag to calculate the start and end address of our loaded kernel:
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ section .text
|
|||||||
bits 32
|
bits 32
|
||||||
start:
|
start:
|
||||||
mov esp, stack_top
|
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_multiboot
|
||||||
call test_cpuid
|
call test_cpuid
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ bits 64
|
|||||||
long_mode_start:
|
long_mode_start:
|
||||||
call setup_SSE
|
call setup_SSE
|
||||||
|
|
||||||
; call rust main
|
; call rust main (with multiboot pointer in rdi)
|
||||||
call rust_main
|
call rust_main
|
||||||
.os_returned:
|
.os_returned:
|
||||||
; rust main returned, print `OS returned!`
|
; rust main returned, print `OS returned!`
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ extern crate spin;
|
|||||||
mod vga_buffer;
|
mod vga_buffer;
|
||||||
|
|
||||||
#[no_mangle]
|
#[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
|
// ATTENTION: we have a very small stack and no guard page
|
||||||
vga_buffer::clear_screen();
|
vga_buffer::clear_screen();
|
||||||
println!("Hello World{}", "!");
|
println!("Hello World{}", "!");
|
||||||
|
|||||||
Reference in New Issue
Block a user