Глава 12. Демонстрация работы обработчика исключения страничного нарушения.
Для того, чтобы показать, как реально работает обработчик исключения страничного нарушения, в нашем примере введены следующие элементы:
Сегмент большого размера Big_segment - он расположен по адресу 3f0000h, т.е. почти в конце 4-го мегабайта и имеет размер больше 4Мб, благодаря чему этот сегмент отображается в трёх таблицах страниц и использование этого обработчик сегмента заставит обработчик использовать текущую таблицу страниц и создать две новых, т.е. функционально он будет задействован полностью. Big_segment создаётся следующим образом:
| mov eax,3f0000h ; Начало сегмента по адресу < 4Мб. mov cx,8092h ; Сегмент данных со страничной гранулярностью. mov edx,1100 ; Предел сегмента равен 1100 страниц, ; т.е. более 4Мб. call set_descriptor ; Big_segment. Стек определён как обычный сегмент данных
| lea dx,Stack_seg_start add eax,edx mov dx,1024 mov cl,10010010b ; Для "обычного" стека здесь должно ; было быть не 10010010b, а 10010110b. call set_descriptor ; Stack Для него зарезервирован 1 Кб в конце программы: Stack_seg_start: ; Отсюда будет расти стек. db 1024 dup (?) ; Зарезервировано для стека. При инициализации стека (сразу после входа в защищённый режим), в SP записывается новое значение вершины стека: mov ax,Stack_selector mov ss,ax mov sp,1020 При переходе в защищённый режим в образе CR0 перед его загрузкой сбрасываются все флаги, кроме эмуляции сопроцессора (он может быть установлен или сброшен, но в нашем примере не используется):
| mov eax,cr0 and eax,10h ; Сбрасываем все биты, кроме ME (эмуляция ; сопроцессора может быть включена). or al,1 mov cr0,eax После инициализации защищённого режима и вывода строки "Entering to protected mode..." в программе производятся следующие действия:
| call get_phys_mem_size ; Определяем количество физической ; памяти, установленной в компьютере. mov phys_mem_size,eax ; Выводим сообщение о количестве памяти: mov text_color,1fh lea bx,Memory_size mov dx,0600h call put_zs call put_dd_num lea bx,_bytes_ call put_zs call create_UPMM ; Создаём UPMM. Демонстрация работы обработчика исключения страничного нарушения происходит в цикле, в котором сегмент Big_segment весь последовательно заполняется, причём чем - не важно. При попытке доступа в неотображённую страницу процессор генерирует исключение и его обработчик отображает страницу и весь этот процесс прозрачен для программы:
| ; Заполняем сегмент Big_segment и выводим текущий адрес в нём на экран: mov ax,Big_segment mov es,ax xor edi,edi ; ES:EDI указывает на начало сегмента. mov dx,0a20h lea bx,_page_ call put_zs ; Вывод строки "Page: ". mov dx,0a00h ; Y вывода = 10, X = 0. lea bx,_current_addr_ call put_zs ; Выводим строку "Current address: ". mov ecx,1100 * 1024 ; ECX = 1100 * 1024 - Мы будем записывать двойными словами. Сегмент ; Big_segment лежит в трёх таблицах страниц и заполнение его числами ; демонстрирует не только работу обработчика страничного нарушения по ; отображению страниц но также и динамическое создание новых таблиц ; страниц. mov dh,0ah ; Y вывода на экран. cld paging_demo: mov dl,11h ; X вывода. mov eax,edi call put_dd_num db 67h ; Атрибут размера операнда - stosd по EDI. stosd db 67h ; Атрибут размера операнда - цикл по ECX. loop paging_demo jmp Return_to_R_Mode |
Полностью пример доступен в архиве examp_8.zip (18'366 байт) - файлы examp_8.asm, examp_8.com и pmode_8.lib.
На этом заканчивается раздел, посвящённый управлению памятью, но сама тема ещё будет продолжена. 32-разрядные процессоры, начиная с Pentium-а предоставляют возможность использования страниц, размером 2 и 4 мегабайта, 36-разрядную шину данных, позволяющую адресовать до 64Гб памяти и множество дополнительных средств, призванных повысить производительность работы компьютера, однако, рассмотрение этих технологий требует знания некоторых других - буферов TLB и регистров MSR (и MTRR). Продолжение этой темы см. в разделе "Расширенное управление памятью".
Оглавление | Вопросы? Замечания? Пишите: sasm@narod.ru |
Copyright © Александр Семенко. |