Защити свой компьютер на 100% от вирусов и хакеров
Шрифт:
; 10010010b
CODE_ACC=ACC_PRESENT or ACC.CSEG or ACC_CONFORM ;
10011100b
STACK_ACC=ACC_PRESENT or ACC_DSEG or ACC_DATAWR or ACC.EXPDOWN
; 1001011 Ob
;Размеры сегментов
CSEG SIZE=65535
DSEG_SIZE=65535
STACK_SIZE=65535
; Смещения дескрипторов
CS_DESCR=(gdt_cs-gdt_0)
DS_DESCR=(gdt_ds-gdt_0)
SS_DESCR=(gdt_ss-gdt_0)
Константы значений портов
CMOS_PORT equ 070h
STATUS_PORT equ 064h
SHUTDOWN equ 0FEh
A20_PORT equ 0D1h
A20_ON equ 0DFh
A20_OFF equ 0DDh
INT_MASK_PORT equ 021h
KBD_PORT_A equ 060h
start:
;
call init_protected_mode
; Сам переход
call set_protected_mode
; Возврат в реальный режим
call set_real_mode
; Печатаем сообщение "Light General"
mov ah, 09h
lea dx, qw
int 21h
; Выход в DOS
mov ax, 4C00h
int 21h
; Макрокоманда для установки адреса для дескриптора
; в глобальной таблице дескрипторов GDT.
setgdtentry MACRO
mov [desc_struc.base_l][bx], ax
mov [desc_struc.base_h][bx], dl
ENDM
init_protected_mode PROC
mov ax, ds
mov dl, ah
shr dl, 4
shl ax, 4
; Устанавливаем адрес сегмента данных
; в глобальной таблице дескрипторов
mov bx, offset gdt_ds
setgdtentry
add ax, offset gdtr
adc dl, 0
; Останавливаем адрес сегмента GDT в глобальной таблице дескрипторов
mov bx, offset gdt_gdt
setgdtentry
; Вычисляем абсолютный адрес для сегмента кода ;
в соответствии со значением регистра CS
mov ax, cs
mov dl, ah
shr dl, 4
shl ax, 4
; Устанавливаем адрес сегмента кода ;
в глобальной таблице дескрипторов
mov bx, offset gdt_cs
setgdtentry
; Вычисляем абсолютный адрес для сегмента стека ;
в соответствии со значением регистра SS
mov ax, ss
mov dl, ah
shr dl, 4
shl ax, 4
; Устанавливаем адрес сегмента стека ;
в глобальной таблице дескрипторов
mov bx, offset gdt_ss
setgdtentry
; Перехватываем рестарт.
pushds
mov ax, 40h
mov ds, ax
mov word ptr ds:[0067h], offset shutdown_return
mov word ptr ds:[0069h], cs
pop ds
; Запрещаем маскируемые прерывания
cli
in al, INT_MASK_PORT
or al, OFFh
out INT_MASK_PORT, al
mov al, 8Fh
out CMOS_PORT, al
jmp $+2 mov al, 5
out CMOS_PORT+1, al
ret
init_protected_mode ENDP
;
set_protected_mode PROC
; Открываем адресную линию А20 для доступа свыше 1 Мбайт
call enable_a20
; Сохранение значения регистра SS для реального режима
mov real_ss, ss
; Перевод компилятора Turbo Assembler в улучшенный режим.
; IDEAL – это не команда и не оператор, это директива, влияющая
; только на интерпретацию дальнейших строк листинга
ideal
р286
;Загружаем регистр глобальной таблицы дескрипторов GDTR
lgdt[QWORD gdt_gdt] ; db OFh,01h,16h dw offset gdt_gdt ;
Переводим процессор в защищенный режим
mov ax, 0001h
lmswax ; db OFh,01h,FOh
; Переводим компилятор Turbo Assembler назад в режим MASM
masm
.286
jmp far flush
; db 0EAh
; dw offset flush
; dw CS_DESCR
flush:
; Останавливаем в регистр SS селектор сегмента стека
mov ax, SS_DESCR
mov ss, ax
; Устанавливаем в регистр DS селектор сегмента данных
mov ax, DS_DESCR
mov ds, ax
; Записываем в строку qw символ "L" и выходим из подпрограммы
mov byte ptr ds:[offset qw+2],"L"
ret
set_protected_mode ENDP
; Подпрограмма, возвращающая процессор в реальный режим
set_real_mode PROC
; Сохраняем значение регистра SP для реального режима
mov real_sp, sp
; Выполняем CPU Reset (рестарт процессора)
mov al, SHUT_DOWN
out STATUS_PORT, al
; Ждем, пока процессор перезапустится
wait_reset:
hlt
jmp wait_reset
; C этого места программа выполняется после перезапуска процессора
shutdown_return:
; Устанавливаем регистр DS в соответствии с регистром CS
pushcs
pop ds
; Восстанавливаем указатели на стек
; по ранее сохраненным значениям
mov ss, real_ss
mov sp, real_sp
; Закрываем адресную линию А20
call disable_a20
; Разрешаем немаскируемые прерывания
mov ax, 000dh
out CMOS_PORT, al
; Разрешаем маскируемые прерывания
in al, INT_MASK_PORT
and al, 0
out INT_MASK_PORT, al
sti
ret
set_real_mode ENDP
; Процедура, открывающая адресную линию А20. После открытия
; адресной линии программам будет доступна память свыше 1 Мбайт
enable_a20 PROC
mov al, A20_PORT
out STATUS_PORT, al
mov al, A20_ON