Простая программка, переводящая процессор в защищенный режим, загружающая FS селектором 4-х гигабайтного сегмента данных и переключающаяся обратно в реальный режим.
; fs4gb.asm
; Программа, устанавливающая размер сегмента, адерсуемого регистром FS, 4 Гб
.model tiny
.code
.386p
org 100h
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Структуры
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Сегментный дескриптор
segment_descriptor struct
limit_low dw 0; Младшие два байта поля Segment limit
base_low dw 0; Младшие два байта поля Base Address
base_high0 db 0; Второй байт поля Base Address
type_and_permit db 0; Флаги
flags db 0; Ещё одни флаги
base_high1 db 0; Старший байт поля Base Address
segment_descriptor ends
; Регистр, описывающий GDT
table_register struct
limit dw 0; Table Limit
base dd 0; Linear Base Address
table_register ends
;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Код
;
;;;;;;;;;;;;;;;;;;;;;;;;;;
start:
; Подготавливаем DS
push cs
pop ds
; Открываем вентиль A20
call open_A20
; Запрещаем прерывания
call disable_interrupts
; Инициалиируем GDT
call initialize_gdt
; Переключаем режим
call set_PE
; загрузить новый селектор в регистр FS
mov ax, 8
mov fs, ax
call clear_PE
call enable_interrupts
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Данные
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Глобальная таблица дескрипторов
GDT label byte
; Нулевой дескриптор
segment_descriptor <>
; Дескриптор сегмента данных, базовый адрес 0, размер 4Gb, Read-Write
segment_descriptor <0ffffh, 0, 0, 10010010b, 10001111b, 0>
; 10010010b - 1001, C/D - 0, 0, R/W - 1, 0
; 10001111b - G - 1, 000, Limit - 1111
; Данные для загрузки в GDTR
gdtr table_register <$ - GDT - 1, 0>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Служебные функции
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Открывает вентиль A20
open_A20:
in al, 92h
or al, 2
out 92h, al
ret
; Инициализирует GDT
initialize_gdt:
; Вычисляем линейный адрес начала массива дескрипторов
call cs_to_eax
add eax, offset GDT
; Записываем его в структуру
mov dword ptr gdtr.base, eax
; Загружаем GDTR
lgdt fword ptr gdtr
ret
; Запрещает маскируемые и немаскируемые прерывания
disable_interrupts:
cli; запретить прерывания
in al, 70h; индексный порт CMOS
or al, 80h; установка бита 7 в нем запрещает NMI
out 70h, al
ret
; Разрешает маскируемые и немаскируемые прерывания
enable_interrupts:
in al, 70h; индексный порт CMOS
and al, 7Fh; сброс бита 7 отменяет блокирование NMI
out 70h, al
sti; разрешить прерывания
ret
; Устанавливает флаг PE
set_PE:
mov eax, cr0; прочитать регистр CR0
or al, 1; установить бит PE,
mov cr0, eax; с этого момента мы в защищенном режиме
ret
; Сбрасывает флаг PE
clear_PE:
mov eax, cr0; прочитать CR0
and al, 0FEh; сбросить бит PE
mov cr0, eax; с этого момента мы в реальном режиме
ret
; Вычисляет линейный адрес начала сегмента кода
cs_to_eax:
mov eax, 0
mov ax, cs
shl eax, 4
ret
end start
После выполнения этой программы можно делать, например, такие вещи:
…
mov eax, 10000000; десять мегабайт
mov word ptr fs:[eax], 1234h
…
И оно будет работать! Примерно это и называется unreal-режимом.
Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет
studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав!Последнее добавление