; Программа, выводящая текст "Hello word!" из защищенного режима.
format MZ
entry codeseg:start
;===============================================================[Служебные макросы]====
; Запрещает маскируемые и немаскируемые прерывания
macro disable_interrupts {
cli ; запретить прерывания
in al, 70h ; индексный порт CMOS
or al, 80h ; установка бита 7 в нем запрещает NMI
out 70h, al
}
; Разрешает маскируемые и немаскируемые прерывания
macro enable_interrupts {
in al, 70h ; индексный порт CMOS
and al, 7Fh ; сброс бита 7 отменяет блокирование NMI
out 70h, al
sti ; разрешить прерывания
}
; Устанавливает флаг PE
macro set_PE {
mov eax, cr0 ; прочитать регистр CR0
or al, 1 ; установить бит PE
mov cr0, eax ; с этого момента мы в защищенном режиме
}
; Сбрасывает флаг PE
macro clear_PE {
mov eax, cr0 ; прочитать регистр CR0
and al, 0FEh ; сбросить бит PE
mov cr0, eax ; с этого момента мы в реальном режиме
}
;====================================================================[Сегмент кода]====
segment codeseg
use16
start:
; Подготовить сегментные регистры
push cs
pop ds ; DS - сегмент данных (и кода) нашей программы
push 0xB800
pop es ; ES - сегмент видеопамяти
disable_interrupts ; запретить прерывания
set_PE ; перейти в защищенный режим
; Установка текстового режима 3 (80x25, цвета 16/8, адрес видео буфера 0xB800)
mov ax, 3
int 10h
xor di, di ; ES:DI - начало видеопамяти
; Вывод на экран пробелов с атрибутом 1Ah
mov ax, 1A20h ; пробел с атрибутом 1Ah
mov cx, length_1 ; заполнить этим символом начало экрана
rep stosw
; Вывод на экран строки 'Hello word!'
mov si, message ; DS:SI - выводимый текст
mov cx, message_size ; количество символов
rep movsw ; вывод текста
; Вывод на экран пробелов с атрибутом 1Ah
mov ax, 1A20h ; пробел с атрибутом 1Ah
mov cx, length_2 ; заполнить этим символом остаток экрана
rep stosw
clear_PE ; переключиться в реальный режим
enable_interrupts ; разрешить прерывания
; Подождать нажатия любой клавиши
mov ah, 0
int 16h
; Выход
mov ax, 0x4C00
int 21h
;==========================================================================[Данные]====
; текст сообщения с атрибутом после каждого символа для прямого вывода на экран
message db 'H',1Ah, 'e',1Ah, 'l',1Ah, 'l',1Ah, 'o',1Ah, ',',1Ah, ' ',1Ah
db 'w',1Ah, 'o',1Ah, 'r',1Ah, 'l',1Ah, 'd',1Ah, '!',1Ah
message_size = ($ - message)/2 ; его длина в словах
length_1 = ((80*25)-message_size) shr 1 ; количество пробелов до текста
length_2 = (80*25)-length_1-message_size ; количество пробелов после текста
;======================================================================================