Как получить информацию о BIOS VESA

Я следую инструкциям Phil-Opp о написании ОС в Rust, и, немного поиграв с ним, я хочу поиграть с отображением реальной графики на экране.

Я выяснил, что, вероятно, я должен начать с использования Linear Frame Buffer, с VESA. Я нашел несколько уроков на osdev.org здесь и здесь, но они продолжают говорить о "функциональных кодах" и es:di. Вторая ссылка говорит следующее:

FUNCTION: получить информацию о BIOS VESA

Код функции: 0x4F00

Описание: возвращает информацию о BIOS VESA, включая производителя, поддерживаемые режимы, доступную видеопамять и т.д. Вход: AX = 0x4F00

Вход: ES: DI = Сегмент: указатель смещения, где хранить информацию о структуре VESA BIOS.

Выход: AX = 0x004F при успехе, другие значения указывают на то, что VESA BIOS не поддерживается.

Во всяком случае, вышеприведенная функция возвращает следующую структуру и сохраняет ее в ES: DI, поскольку они были на входе. При вводе ES: DI должен содержать указатель на следующую структуру:

vbe_info_structure:.signature db "VBE2"; indicate support for VBE 2.0+.table_data: resb 512-4; reserve space for the table below

Хотя я изучил некоторые уроки языка ассемблера, я понятия не имею, что такое "код функции". Из того, что я понимаю, если я mov ax, 0x4f00 и создаю структуру, подобную той, что была выше, она волшебным образом перезапишет структуру, которую я мог бы передать в качестве параметра для моего кода Rust? Как мне, или мне нужно, установить мой es:di? (Из исследования я подумал, что он просто автоматически устанавливается на современных процессорах)

Должен ли я делать все это в Inline Assembly вместо этого? Должен ли я использовать UEFI и переписывать свое ядро? Мне бы очень хотелось, если бы вы могли привести пример доступа к vbe_info_structure в коде Rust (я работаю в long mode).

Вот мой файл boot.asm до сих пор, но он пока не работает: https://gist.github.com/nebrelbug/5a0042d4de32f942bb72e71fe282bdd2. Спасибо!

Ответ 1

В файле boot.asm у вас есть:

get_vesa_info:
    mov ax, 0x4f00
    mov [es:di], vbe_info_structure
    int 0x10
    ret

Третья строка должна быть заменена на

    mov di, vbe_info_structure

Объяснение: как и сейчас, он пытается записать константу vbe_info_structure по адресу, на который указывает es: di (что не определено в вашем случае). Вместо этого вы должны загрузить адрес vbe_info_structure в di и передать его в процедуру int 0x10.

Кстати, int 0x10 выполняет несколько функций. Чтобы указать, какой из них вы хотите вызвать, вы передаете "код функции" в регистре топора. Подумайте о функциональном коде как имени функции (в сборке нет имен, просто номеров и адресов).

Кроме того, вам нужно правильно настроить es. Либо сделайте

push ds
pop es

предполагая, что ds уже указывает на section.data или с помощью директивы ассемблера (assume es section.data? - не уверен в этом, это было давно, так как я использовал ассемблер). Или может быть так:

mov ax, @section.data
mov es, ax

что должно быть сделано до загрузки 0x4f00 в топор, конечно.