Сделай Сам Свою Работу на 5

Обработка событий в MSDOS

В процессе работы могут возникать некоторые события. События бывают синхронные и асинхронные. Синхронные события - это те, которые происходят в процессе выполнения программы всегда в одном и том же месте. Асинхронные события - это те, которые происходят независимо от работы программы. К синхронным событиям относятся вызовы системы DOS, BIOS. К асинхронным событиям относятся вызовы обработчиков нажатий клавиши на клавиатуре, поступление символа по каналу связи и т.п. Асинхронные прерывания - это, обычно, аппаратные прерывания.

Первые 1024 байта - это таблица векторов (Interupt Table), содержащая для каждого из 256 векторов двухсловный указатель на обработчик. При вызове соответствующего прерывания контроллер прерываний сохраняет в стеке регистр флагов, устанавливает запрет прерываний с большим или равным номером IRQ (для аппаратных прерываний) сохраняет в стеке CS, IP и передает управление обработчику прерываний. Обработчик должен выполнить необходимые действия и вернуть управление командой IRET. В некоторой литературе ошибочно написано о необходимости разрешить прерывания перед возвратом, - этого делать не следует, т.к. после разрешения прерывания, перед инструкцией IRET начинается обработка следующего прерывания стоящего в очереди, и есть высокая вероятность получения сообщения:

Internal Stack Overflow. System halted.

Возможно два способа обработки событий своим обработчиком:

  1. полная замена обработчика;
  2. встраивание в цепочку обработчиков прерывания.

К полной замене приходится прибегать довольно редко. Обычно это используется для написания обработчика "пустых" векторов. Встраивание в цепочку обработчиков прерывания используют все программные драйверы, которым необходимо получить управление при возникновении тех или иных событий.

Встраивание в цепочку обработчиков прерывания происходит по следующей схеме:

Иногда необходимо получить управление как до старого обработчика, так и после него. Это производится следующим образом:

PUSHF [Предобработка] CALL FAR [Адрес старого обработчика] PUSHF [Постобработка] POPF RETF 2 ; с сохранением флагов старого обработчика

Команды Pushf и Call Far имитируют Int, команды Pushf, Popf, Retf 2 делают Iret, но возвращают вызвавшей программе флаги, которые вернул старый обработчик.



Приемы "красивого встраивания" с заменой части команды:

Start: JMP installinterupt: pushf ; Предобработка db 9Ah ; call far ;db 0EAh ; JMP FARint9_sav dd 0 ; два слова pushf ; -- ; Постобработка ; ¦ для JMP FAR ненужно, т.к. popf ; ¦ сюда управление не передается retf 2 ; ---Install: ;;;;;;;;;;;;;;;; push cs pop ds mov ax,3509h ; дать адрес старого обработчика int 21h ; прерывания mov word ptr [int9_sav],bx mov word ptr [int9_sav+2],es lea dx,int9 ; или mov dx, offset int9 mov ah,25h ; установить обработчик прерывания int 21h ; al уже установлен

Структура диска

Таблица разделов диска

Начальный сектор жеского диска содержит главную корневую запись, которая загружается в память и выполняется.

Последняя часть этого сектора содержит таблицу разделов - 4-элементную таблицу с 16-байтовыми элементами. Этой таблицей манипулирует программа FDISK (или эквивалентная утилита в иной операционной системе).

Во время загрузки ROM-BIOS загружает главную корневую запись и передает управление на ее код. Этот код считывает таблицу разделов, чтобы определить раздел, помеченный как активный. Затем в память считывается корректный корневой сектор и выполняется.

Таблица 1. Структура главной корневой записи и таблицы разделов

Смещение Длина Содержимое
000h Корневая запись (MSB)
1BEh Описатель раздела 1 (см. табл.2)
1CEh Описатель раздела 2
1DEh Описатель раздела 3
1EEh Описатель раздела 4
1FEh Подпись таблицы разделов (значение AA55h)

Таблица 2. Структура описателя раздела

Смещение Длина Содержимое
00h Признак активности раздела (0 - не активен, 80h - активен)
01h Номер поверхности диска, с которой начинается раздел
02h Номер цилиндра и номер сектора, с которых начинается раздел
04h Код раздела (см. табл.3)
05h Номер поверхности диска, на которой заканчивается раздел
06h Номер цилиндра и номер сектора, на которых заканчивается раздел
08h Абсолютный (логический) номер начального сектора раздела
0Ch Размер раздела (число секторов)

Код раздела используется для определения наличия и положения на диске основного и расширенного разделов. После обнаружения нужного раздела его размер и координаты можно извлечь из соответствующих полей описателя. Если в поле кода раздела записан 0, то описатель считается пустым, то есть он не определяет на диске никакого раздела.

Таблица 3. Коды разделов операционных систем Microsoft

Код Вид раздела Размер Тип FAT ОС
01h Основной 0-15 Мбайт FAT12 MS-DOS 2.0
04h Основной 16-32 Мбайт FAT16 MS-DOS 3.0
05h Расширенный 0-2 Гбайт - MS-DOS 3.3
06h Основной 32 Мбайт-2 Гбайт FAT16 MS-DOS 4.0
0Bh Основной 512 Мбайт-2 Гбайт FAT32 OSR2
0Ch Расширенный 512 Мбайт-2 Тбайт FAT32 OSR2
0Eh Основной 32 Мбайт-2 Гбайт FAT16 Windows 95
0Fh Расширенный 0-2 Гбайт - Windows 95

За операционными системами других фирм зарезервированы следующие коды:

  • 02h - раздел CP/M;
  • 03h - раздел Xenix;
  • 07h - раздел OS/2 (файловая система HPFS).

Замечания:

  1. Номера цилиндра и сектора занимают 10 и 6 бит соответственно:
c c c c c c c c c c s s s s s s

  1. Они упорядочены так, что, когда вы загружаете CX 16-битовым значением, оно готово для вызова прерывания INT 13h для чтения нужной порции диска. Таким образом, после чтения Главной записи загрузки в область памяти sect_buf, код
4. CMP byte ptr sect_buf[01BEh], 80h

5. проверит, активен ли первый раздел, а код

6. MOV CX, sect_buf[01C0h]

7. загрузит CX для вызова INT 13h для чтения корневого сектора раздела № 1.

  1. Значение "относительного сектора" по смещению 08h в каждом разделе эквивалентно головке, сектору и цилиндру начального адреса раздела. Относительный сектор 0 совпадает с цилиндром 0, головкой 0, сектором 1. Относительный номер сектора прирастает сначала по каждому сектору на головке, затем по каждой головке и наконец по каждому цилиндру.

Применима формула:

отн_сек = (#Цил * сек_на_цил * головок) + (#Гол * сек_на_цил) + (#Сек -1)

Разделы начинаются с четного номера цилиндра, за исключением первого раздела, который может начинаться с цилиндра 0, головки 0, сектора 2 (поскольку сектор 1 занят Главной записью загрузки).

Когда корневая запись раздела получает управление, DS:SI указывает на соответствующий элемент таблицы разделов.



©2015- 2019 stydopedia.ru Все материалы защищены законодательством РФ.