CodeNet / Платформы / Пишем ОС / Пишем "многозадачную" ОС в "Real Mode"
Реализация многозадачности в RealMode.
Загрузка задачи.
В реальном режиме мы имеем 640Kb памяти - 10 сегментов по 64Kb. В первый сегмент нам лучше пока не соваться - эта область BIOS. Для простоты предположим, что каждая задача нашей ОС - это COM файл MS-DOS.
COM-программы содержат единственный сегмент (или, во всяком случае, не содержат явных ссылок на другие сегменты). Образ COM-файла считывается с диска и помещается в память, начиная с PSP:0100. Заметим, что COM-программа может использовать множественные сегменты, но она должна сама вычислять сегментные адреса, используя PSP как базу.
COM-программы предпочтительнее EXE-программ, когда дело касается небольших ассемблерных утилит. Они быстрее загружаются, ибо не требуется перемещения сегментов, и занимают меньше места на диске, поскольку заголовок EXE и сегмент стека отсутствуют в загрузочном модуле.
В MS-DOS после загрузки двоичного образа:
- CS, DS, ES и SS указывают на PSP
- SP указывает на конец сегмента PSP (обычно 0fffeH, но может быть и меньше, если полный 64K сегмент недоступен). Слово по смещению 06H в PSP указывает, какая часть программного сегмента доступна.
- Вся память системы за программным сегментом распределена программе.
- Слово 00H помещено (PUSH) в стек.
- IP содержит 100H (первый байт модуля) в результате команды JMP PSP:100
Наша задача при загрузке файла проделать те-же самые действия, что-бы программы ни коим образом не догадывалась об отстутствии ее родной ОС.
Переключение задач.
Предположим, что каждая COM-программа занимает в памяти один сегмент. Обычно это выглядит следующим образом:
18.2 раза в секунду приходит аппаратное прерывание, и процессор отвлекается на выполнение некоторой процедуры - восьмого прерывания (int 08h). При этом он сохраняет в стеке регистр флагов (PUSHF), и регистры указывающие на текущую команду (CS:IP) (PUSH CS, PUSH IP). Всего 6 байт. После окончания аппаратного прерывания эти регистры восстанавливаются и основная программа продолжает свое выполнение.
Наша задача, в время выполнения прервания подменять стек таким образом, что-бы после восстановления регистров выполнялась другая программа, находящаяяся в памяти.
Структура дескрипторов задачи.
При наилучшем раскладе возможна загрузка восьми задач - 640Kb/64Kb=10, то есть всего имеем десять сегментов - один под переменные DOS, и один под ядро, вот и остается только восемь.
Для каждой из восьми возможных задач и для ядра, заводим структуру:
task8 DB ? ;¦ char id; (255 - no task) DD ? ;¦ void far * pointer; DW 255 DUP(?) ;- unsigned int stack[255]; }
id - идентификатор задачи, если загружена, то ее номер, 255 - если не загружена и 254 - если приостановлена.
pointer - Точка входа в задачу.
stack[255] - В это место будем сохранять некоторые регистры задачи при переключении, кроме того здесь будет хранится указатель на стек задачи, где сохранены остальные регистры, ну и еще что-нибуть - если понадобится.
Оставить комментарий
Комментарии
начиная с 0060:0000 и до B000:0000 место свободно, однако, гарантируется наличие только 32КБ памяти (неспроста загрузочный сектор помещается в 0000:7C00). Остальное нужно спросить у BIOS либо померить самому.