Защищенный режим процессоров Intel


Пример мультизадачного монитора - часть 10


Обратите внимание на процедуры _load_task_register и _jump_to_task, выполняющие загрузку регистра задачи TR и переключение на другую задачу соответственно.

Листинг 15. Процедуры для инициализации, перехода в защищённый режим и возврата в реальный режим, для загрузки регистра TR и переключения задач. Файл tossyst.asm ----------------------------------------------------------- IDEAL MODEL SMALL RADIX 16 P286 DATASEG include "tos.inc" PUBLIC _beep ; Область памяти для инициализации IDTR idtr idtr_struc <,,,0> ; Область памяти для инициализации GDTR gdt_ptr dw (8*15)-1 ; размер GDT, 15 элементов gdt_ptr2 dw ? gdt_ptr4 dw ? ; Область памяти для записи селектора задачи, ; на которую будет происходить переключение new_task dw 00h new_select dw 00h ; Область памяти для хранения регистров, ; используется для возврата в реальный режим real_ss dw ? real_sp dw ? real_es dw ? protect_sel dw ? init_tss dw ? CODESEG PUBLIC _real_mode,_protected_mode,_jump_to_task PUBLIC _load_task_register, _load_idtr, _enable_interrupt ; ------------------------------------------------------------------- ; Процедура для переключения в защищённый режим. ; Прототип для вызова: ; void protected_mode(unsigned long gdt_ptr, unsigned int gdt_size, ; unsigned int cseg, unsigned int dseg) ; ------------------------------------------------------------------- PROC _protected_mode NEAR push bp mov bp,sp ; Параметр gdt_ptr mov ax,[bp+4] ; мл. слово адреса GDT mov dx,[bp+6] ; ст. слово адреса GDT mov [gdt_ptr4], dx ; запоминаем адрес GDT mov [gdt_ptr2], ax ; Параметр gdt_size mov ax,[bp+8] ; получаем размер GDT mov [gdt_ptr], ax ; и запоминаем его ; Параметры cseg и dseg mov ax,[bp+10d] ; получаем селектор сегмента кода mov dx,[bp+12d] ; получаем селектор сегмента данных mov [cs:p_mode_select], ax ; запоминаем для команды mov [protect_sel], dx ; перехода far jmp ; Подготовка к возврату в реальный режим push ds ; готовим адрес возврата mov ax,40h ; из защищённого режима mov ds,ax mov [WORD 67h],OFFSET shutdown_return mov [WORD 69h],cs pop ds ; Запрещаем и маскируем все прерывания cli in al, INT_MASK_PORT and al, 0ffh out INT_MASK_PORT, al ; Записываем код возврата в CMOS-память mov al,8f out CMOS_PORT,al jmp delay1 delay1: mov al,5 out CMOS_PORT+1,al call enable_a20 ; открываем линию A20 mov [real_ss],ss ; запоминаем регистры SS и ES mov [real_es],es ; Перепрограммируем контроллер прерываний ; для работы в защищённом режиме mov dx,MASTER8259A mov ah,20 call set_int_ctrlr mov dx,SLAVE8259A mov ah,28 call set_int_ctrlr ; Загружаем регистры IDTR и GDTR lidt [FWORD idtr] lgdt [QWORD gdt_ptr] mov ax, 0001h ; переключаем процессор lmsw ax ; в защищённый режим ; jmp far flush db 0eah dw OFFSET flush p_mode_select dw ? LABEL flush FAR mov dx, [protect_sel] mov ss, dx mov ds, dx mov es, dx ; Обнуляем содержимое регистра LDTR mov ax, 0 lldt ax pop bp ret ENDP _protected_mode ; ---------------------------------------------------- ; Возврат в реальный режим. ; Прототип для вызова ; void real_mode(); ; ---------------------------------------------------- PROC _real_mode NEAR ; Сброс процессора cli mov [real_sp], sp mov al, SHUT_DOWN out STATUS_PORT, al rmode_wait: hlt jmp rmode_wait LABEL shutdown_return FAR ; Вернулись в реальный режим mov ax, DGROUP mov ds, ax assume ds:DGROUP mov ss,[real_ss] mov sp,[real_sp] in al, INT_MASK_PORT and al, 0 out INT_MASK_PORT, al call disable_a20 mov ax, DGROUP mov ds, ax mov ss, ax mov es, ax mov ax,000dh out CMOS_PORT,al sti ret ENDP _real_mode ; ------------------------------------------------------- ; Загрузка регистра TR. ; Прототип для вызова: ; void load_task_register(unsigned int tss_selector); ; ------------------------------------------------------- PROC _load_task_register NEAR push bp mov bp,sp ltr [bp+4] ; селектор для текущей задачи pop bp ret ENDP _load_task_register ; ------------------------------------------------------- ; Переключение на задачу. ; Прототип для вызова: ; void jump_to_task(unsigned int tss_selector); ; ------------------------------------------------------- PROC _jump_to_task NEAR push bp mov bp,sp mov ax,[bp+4] ; получаем селектор ; новой задачи mov [new_select],ax ; запоминаем его jmp [DWORD new_task] ; переключаемся на ; новую задачу pop bp ret ENDP _jump_to_task ; ------------------------------ ; Открываем линию A20 ; ------------------------------ PROC enable_a20 NEAR push ax mov al, A20_PORT out STATUS_PORT, al mov al, A20_ON out KBD_PORT_A, al pop ax ret ENDP enable_a20 ; ------------------------------ ; Закрываем линию A20 ; ------------------------------ PROC disable_a20 NEAR push ax mov al, A20_PORT out STATUS_PORT, al mov al ,A20_OFF out KBD_PORT_A, al pop ax ret ENDP disable_a20 ; ----------------------------------------------------------- ; Готовим структуру для загрузки регистра IDTR ; Прототип для вызова функции: ; void load_idtr(unsigned long idt_ptr, word idt_size); ; ----------------------------------------------------------- PROC _load_idtr NEAR push bp mov bp,sp mov ax,[bp+4] ; мл.


Начало  Назад  Вперед



Книжный магазин