Итерация свойственна человеку. Рекурсия божественна.
(с) Л. Питер Дойч
Итак... Если кто экспериментировал в написании бутовых прог для 386наследников, предлагаю вашему вниманию свою, отнюдь не оригинальную, но всё ж идею - запустить графическую ось прям с бутсектора со всеми потрохами. Задача - в 512 байт всунуть если не целый Windows-MacOS-Linux - нужное подчеркнуть, то хотя бы что-то, что рисовало б на экране кружочки, буковки или ещё чё. Поскольку дальше белого квадрата (в ответ К.Малевичу) моя хуйдожественная фантазия не продвинулась, я решил на нём, родном и остановиться...
Итак. В качестве Переводчика я взял малоинтересный, но высокоэффективный в такого рода делах странновато-корявый пакет под названием... дай бог памяти - 86utils (или типа того). Если не считать, что его общение создаёт впечатление деревенской недалёкости, то сей премудрый ассемблер (а вкупе с ним и насишный компайлер такого же характера), то он вполне годен для написания всяких бутовых штук - от ОСей до вирусов...
Итак (снова Итак))). Берём и создаём файл с оригинальнейшим названием - boot.s (а всё это я исполняю под надёжной защитой Linux в оболочке MC - но ничто не помешает нам запустить Far под Windows и исполнять ТАМ). Начинаем ваять:
use16 ; вдруг as думает что надо 32х разрядную адресацию включать?
org 0000 ; люблю бессмысленные команды))))
cli ; запрещаем все немаскируемые прерывания
in al,0x70 ; и
or al,#0x80 ; маскируемые
out 0x70,al ; тоже
mov ax,#0x0013 ; включим какой-нить
int #0x10 ; VGA-режим
call empty_8042 ; подождём разчехления клавы
mov al,#0xd1 ; подадим команду ждать команды ( :) )
out #0x64,al ; отправим её
call empty_8042 ; подождём
mov al,#0xdf ; подадим команду открыть магистраль A20
out #0x60,al ; и сольём её
call empty_8042 ; опять ждём
mov ax,#0x0000 ; зададим точкой отсчёта
mov ds,ax ; начало адресного пространства
lgdt gdtr+0x7c00 ; и загрузим таблицу сегментов
mov ax,#0x0001 ; потом расскажем процессору
lmsw ax ; что нужно переключиться в режим защиты
jmp #0x0008:protect+0x7c00 ; и загрузить в сегмент текущей задачи "правильный" с точки зрения режима адрес
use32 ; скажем переводчику, что мы уже в 32х битовом гиперпространстве
protect: ; и вот мы уже летим на совсем другой скорости
mov ax,#0x0010 ; теперь настроим регистр данных на такой же "правильный" адрес
mov es,ax ; и напомним процу номер нашего звездолёта
mov edi,#0x000a0000 ; поскольку система отсчёта у нас идёт от пола к потолку, соотв. видеопамять для вышеупомянутого режима лежит (или висит) в данной плоскости)))
mov cx,#320*50 ; а сюда запишем размер видеопамяти в четырёхбайтовых словах
mov eax,#0x07070707 ; за основу возьмём белую краску - и макнём в неё сразу 4 кисточки
repz ; и начнём
stosd ; мазать
stop_running: ; тут мы жостко затупим
jmp stop_running ; ожидая освежающего нажатия RESET
empty_8042: ; подпрограмма ожидания очистки стека южного моста
in al,#0x64 ; посмотрим,
test al,#2 ; что нам говорит
jnz empty_8042 ; мост и снова посмотрим...
ret ; или выйдем из цикла
gdtr: ; тут мы запишем адрес таблицы сегментов
dw 0x0018 ; это её размер (3 поля - одно пустое, одно - для программы и ещё одно - для данных).
dd gdt+0x7c00 ; это - адрес таблицы сегментов
gdt: ; таблица сегментов собственной персоной
dd 0x00000000,0x00000000 ; это пустое поле - мы его и оставляем пустым
dd 0x0000ffff,0x00cf9a00 ; это - типичное поле кода ( с максимальным размером сегмента)
dd 0x0000ffff,0x00cf9200 ; а это - типичное поле данных
org 0x01fe ; в конце программы неплохо поставить
dw 0xaa55 ; отметку - печать с сертификатом качества, чтобы BIOS "схавал" наш загрузчик.
небольшое резюме:
этот код я подсмотрел в буте FreeBSD, выкинув из него всё, что мне казалось лишним, так что не претендую на оригинальность. скажу лишь, что сначала я хотел вместо обращения к портам клавиатуры (южного моста) пойти другим путём - а именно обращением в порт 92 (т.н. "быстрый A20"):
in al,#0x92 ;
or al,#0x02 ; "fast A20" version
out #0x92,al ; some chips have only this
но, похоже, что виртуалка, на которой я всё это испытывал (qemu) - наотрез оказалась "хавать" мой код. или эт я чё напутал? хз, короче, остановился на старом, проверенном, дедовском способе.
и заместо пришедшего из эпохи Р2Д2 "звёздных войн" загрузки машинного слова (lmsw) я тоже планировал поставить более "современный" способ:
mov eax,cr0 ; загрузить регистр состояния
or al,#0x01 ; помухлевать с ним
mov cr0,eax ; передать дальше
опять же - или собственная криворукость или криворукость создателей qemu - но пришлось опять же - тулить более архаичные средства.
но пацан сказал - пацан сделал - на экране - табула раса - на душе - приятный позитив, как после секаса с мулаткой, мы таки уломали глупую машину совершить нам маленькое чудо)))
желаю творческих успехов