I'm following through the Phil-Opp Tutorials about writing an OS in Rust, and, after playing around with it a little bit, I want to fiddle with displaying real graphics on the screen.
I've figured out that I should probably start out by using the Linear Frame Buffer, with VESA. I found some tutorials on osdev.org here and here, but they keep on talking about "function codes" and es:di
. The second link says this:
FUNCTION: Get VESA BIOS information
Function code: 0x4F00
Description: Returns the VESA BIOS information, including manufacturer, supported modes, available video memory, etc... Input: AX = 0x4F00
Input: ES:DI = Segment:Offset pointer to where to store VESA BIOS information structure.
Output: AX = 0x004F on success, other values indicate that VESA BIOS is not supported.
Anyway, the above function returns the following structure and stores it in ES:DI as they were on entry. On entry, ES:DI should contain a pointer to the following structure:
vbe_info_structure: .signature db "VBE2" ; indicate support for VBE 2.0+ .table_data: resb 512-4 ; reserve space for the table below
Though I've looked at some assembly language tutorials, I have no idea what a "function code" is. From what I understand, if I mov ax, 0x4f00
, and create a structure like the one above, it will magically overwrite the structure, which I could then pass as a parameter to my Rust Code? How do I, or do I need to, set my es:di
? (From researching, I thought that it was just automatically set on modern processors)
Should I do all of this stuff in Inline Assembly instead? Should I just use UEFI and rewrite my kernel? I would love if you could give an example of how to access the vbe_info_structure in Rust code (I'm running in long mode
).
Here's my boot.asm
file so far, but it doesn't work yet: https://gist.github.com/nebrelbug/5a0042d4de32f942bb72e71fe282bdd2. Thanks!
In your boot.asm file, you have:
get_vesa_info:
mov ax, 0x4f00
mov [es:di], vbe_info_structure
int 0x10
ret
The third line must be replaced by
mov di, vbe_info_structure
Explanation: as it is now, it attempts to write the constant vbe_info_structure at the address pointed to by es:di (which is undefined in your case). What you want instead, is to load the address vbe_info_structure into di, and thus pass it to the int 0x10 routine.
By the way, int 0x10 performs several functions. In order to tell it which one you want to call, you pass the "function code" in the ax register. Think of the function code as the name of the function (there are no names in assembly, just numbers and addresses).
Also, you need to setup es correctly. Either do
push ds
pop es
assuming that ds already points to section.data, or by using an assembler directive (assume es section.data
? -- not sure about this, it's been a long time since I've used an assembler).
Or maybe like this:
mov ax, @section.data
mov es, ax
which should be done before loading 0x4f00 into ax, of course.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With