|
Обработка событий в MSDOS
В процессе работы могут возникать некоторые события. События бывают синхронные и асинхронные. Синхронные события - это те, которые происходят в процессе выполнения программы всегда в одном и том же месте. Асинхронные события - это те, которые происходят независимо от работы программы. К синхронным событиям относятся вызовы системы DOS, BIOS. К асинхронным событиям относятся вызовы обработчиков нажатий клавиши на клавиатуре, поступление символа по каналу связи и т.п. Асинхронные прерывания - это, обычно, аппаратные прерывания.
Первые 1024 байта - это таблица векторов (Interupt Table), содержащая для каждого из 256 векторов двухсловный указатель на обработчик. При вызове соответствующего прерывания контроллер прерываний сохраняет в стеке регистр флагов, устанавливает запрет прерываний с большим или равным номером IRQ (для аппаратных прерываний) сохраняет в стеке CS, IP и передает управление обработчику прерываний. Обработчик должен выполнить необходимые действия и вернуть управление командой IRET. В некоторой литературе ошибочно написано о необходимости разрешить прерывания перед возвратом, - этого делать не следует, т.к. после разрешения прерывания, перед инструкцией IRET начинается обработка следующего прерывания стоящего в очереди, и есть высокая вероятность получения сообщения:
Internal Stack Overflow. System halted.
Возможно два способа обработки событий своим обработчиком:
- полная замена обработчика;
- встраивание в цепочку обработчиков прерывания.
К полной замене приходится прибегать довольно редко. Обычно это используется для написания обработчика "пустых" векторов. Встраивание в цепочку обработчиков прерывания используют все программные драйверы, которым необходимо получить управление при возникновении тех или иных событий.
Встраивание в цепочку обработчиков прерывания происходит по следующей схеме:
Иногда необходимо получить управление как до старого обработчика, так и после него. Это производится следующим образом:
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).
Замечания:
- Номера цилиндра и сектора занимают 10 и 6 бит соответственно:
-
c
| c
| c
| c
| c
| c
| c
| c
| c
| c
| s
| s
| s
| s
| s
| s
| Они упорядочены так, что, когда вы загружаете 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.
- Значение "относительного сектора" по смещению 08h в каждом разделе эквивалентно головке, сектору и цилиндру начального адреса раздела. Относительный сектор 0 совпадает с цилиндром 0, головкой 0, сектором 1. Относительный номер сектора прирастает сначала по каждому сектору на головке, затем по каждой головке и наконец по каждому цилиндру.
Применима формула:
отн_сек = (#Цил * сек_на_цил * головок) + (#Гол * сек_на_цил) + (#Сек -1) Разделы начинаются с четного номера цилиндра, за исключением первого раздела, который может начинаться с цилиндра 0, головки 0, сектора 2 (поскольку сектор 1 занят Главной записью загрузки).
Когда корневая запись раздела получает управление, DS:SI указывает на соответствующий элемент таблицы разделов.
Не нашли, что искали? Воспользуйтесь поиском по сайту:
©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.
|