Главная Рефераты по сексологии Рефераты по информатике программированию Рефераты по биологии Рефераты по экономике Рефераты по москвоведению Рефераты по экологии Краткое содержание произведений Рефераты по физкультуре и спорту Топики по английскому языку Рефераты по математике Рефераты по музыке Остальные рефераты Рефераты по авиации и космонавтике Рефераты по административному праву Рефераты по безопасности жизнедеятельности Рефераты по арбитражному процессу Рефераты по архитектуре Рефераты по астрономии Рефераты по банковскому делу Рефераты по биржевому делу Рефераты по ботанике и сельскому хозяйству Рефераты по бухгалтерскому учету и аудиту Рефераты по валютным отношениям Рефераты по ветеринарии Рефераты для военной кафедры Рефераты по географии Рефераты по геодезии Рефераты по геологии Рефераты по геополитике Рефераты по государству и праву Рефераты по гражданскому праву и процессу Рефераты по делопроизводству Рефераты по кредитованию Рефераты по естествознанию Рефераты по истории техники Рефераты по журналистике Рефераты по зоологии Рефераты по инвестициям Рефераты по информатике Исторические личности Рефераты по кибернетике Рефераты по коммуникации и связи |
Курсовая работа: Робота в захищеному режимі мікропроцесораКурсовая работа: Робота в захищеному режимі мікропроцесораМІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ НАЦІОНАЛЬНИЙ ТЕХНІЧНИЙ УНІВЕРСИТЕТ ”ХАРКІВСЬКИЙ ПОЛІТЕХНІЧНИЙ ІНСТИТУТ” Розрахунково-графічне завдання №1 з курсу "Мікропроцесорн системи" Виконав: ст. гр. xxxxxxx xxxxxxxxxxxxx Перевірив: xxxxxxxxx Харків 2006 Зміст 1. Індивідуальне завдання 2. Пояснення до змісту роботи 3. Опис програми 4. Текст програми 5. Результати роботи програми 6. Висновки 1. Індивідуальне завдання Варіант 16 В захищеному режим виконати наступні дії: I. Викликати необхідне згідно із ндивідуальним завданням виключення II. Обробити задане виключення двома засобами: а) прибравши причину виключення; б) пропустивши команду, що визвала виключення. III. Обробити задане зовнішнє переривання. 2. Пояснення до змісту роботи Для виконання завдання необхідно виконати наступні дії: 1) розробити дескриптори усіх необхідних сегментів пам’яті і сформувати з них глобальну дескрипторну таблицю GDT. 2) за допомогою регістра GDTR задати базову адресу і розмір таблиці GDT; 3) розробити дескриптори усіх шлюзів, сформувати з них таблицю IDT. 4) за допомогою регістра IDTR задати базову адресу і розмір таблиці IDT; 5) сформувати дані для повернення в реальний режим; 6) заборонити масковані і немасковані переривання; 7) перевести мікропроцесор у захищений режим; 8) виконати в захищеному режимі дії, задані індивідуальним завданням; 9) повернутися в реальний режим; 10) дозволити масковані і немасковані переривання. Для розуміння принципів програмування роботи в захищеному режимі необхідно розуміти його особливості. Захищений режим має такі особливості роботи з перериваннями (порівнюючи з реальним режимом): 1) вводиться новий тип переривань виключення; 2) замість дальніх адрес в таблиці переривань використовуються дескриптори шлюзів; 3) таблиця переривань може знаходитися в будь-якому місці пам’яті. Виключення поділяються на три типи: - Помилка (trap); - Пастка (fault); - Аварія (abort). Помилка – це виключення, що виникає в ситуації помилкових дій програми й припускається, що таку помилку можна виправити. Виконання програми продовжується починаючи із команди, при якій виникло виключення. Пастка – це виключення, що виникає відразу після виконання команди. Виконання програми продовжується з наступної команди,що йде за командою на якій виникло виключення. На пастках строїться механізм відладки програм. Аварія – це виключення, що не дозволяє продовжити виконання перерваної програми сигналізує про серйозні порушення цілісності системи. 3. Опис програми Для написання програми для виконання разрахункового завдання, скористались модулем PROT і програмою P_INT, що поставляються разом із ндивідуальним завданням. В модулі PROT містяться основні необхідні константи і функції для створення власних таблиць GDT та IDT, для переходу в захищений режим, містяться також заглушки для всіх апаратних і програмних переривань. Програма P_INT містить перевизначення необхідних для роботи, або заданих за індивідуальним завданням переривань, в ній задається вміст таблиць GDT та IDT (в ній визначаються селектори заглушок, або необхідних переривань, на необхідних місцях), програма реалізу перехід в захищений режим, імітує виникнення програмного переривання, а також реалізує вічний цикл, до виникнення апаратного переривання. Після цього реалізується вихід до реального режиму, шляхом скидання мікропроцесору (не працю на нових моделях мікропроцесорів) або шляхом відновлення старої GDT та IDT, і повернення до реального режиму. Нами було додано необхідні по індивідуальному завданню апаратне і програмне переривання, і реалізовано виключну ситуацію для їх виникнення. 4. Текст програми {----Модуль содержит константы, типы переменных, переменные,----} {------процедуры и функции для работы в защищенном режиме-------} unit prot; interface uses crt; const hex_tabl:array[0..15] of char='0123456789ABCDEF'; s2:string='Run time error: исключение '; {--------------Селекторы дескрипторов сегментов---------------} code_sel =$08; { кода программы, } code_sel2 =$10; { кода модуля PROT, } data_sel :word =$18; { данных, } stack_sel :word =$20; { стека, } video_sel :word =$28; { видеопамяти, } mem_sel :word =$30; { расширенной памяти, } {-----------------Биты байтов доступа сегментов---------------} present =$80; { P=1 : сегмент есть в памяти } nosys =$10; { S=1 : сегмент несистемный } exe =$08; { E=1 : сегмент выполняемый } down =$04; { ED=1: сегмент расширяется вниз } wr_ena =$02; { W=1 : разрешена запись в сегмент } rd_ena =$02; { R=1 : разрешено чтение из сегмента } {---------Значения поля TYPE системных дескрипторов-----------} type_int =$06; { шлюза прерывания для 80286 } type_trap =$07; { шлюза исключения для 80286 } type_TSS =$01; { сегмента TSS } type_call =$04; { шлюза вызова } type_task =$05; { шлюза задачи } {-----------------Байт доступа сегмента кода------------------} acc_code=present OR nosys OR exe OR rd_ena; acc_code1=present OR nosys OR exe ; {----------------Байт доступа сегмента данных-----------------} acc_data=present OR nosys OR wr_ena; {----------------Байт доступа сегмента стека -----------------} acc_stack=present OR nosys OR wr_ena OR down; {-----------------Байт доступа шлюза задачи-------------------} acc_task =present OR type_task; type {-------------Структура дескриптора таблицы GDT---------------} t_gdt=record lim_l, { граница сегмента (биты 15-0) } base_l :word; { базовый адрес сегм. (биты 15-0) } base_h, { базовый адрес сегм. (биты 23-16) } acc, { байт доступа } lim_h, { G,D,0,X,граница сегм. (биты 19-16) } base_hh:byte { базовый адрес сегм. (биты 31-24) } end; {-------------Структура дескриптора таблицы IDT---------------} t_idt=record off_l, { смещение (биты 15-0) } sel :word; { селектор } par, { число параметров } acc :byte; { байт доступа } off_h :word { смещение (биты 31-16) } end; {---------------Структура регистров GDTR и IDTR---------------} t_dtr=record lim :word; { граница и } base :longint; { базовый адрес таблицы } end; {-----------------Структура TSS для МП 80286------------------} t_tss_286=record link, { селектор возврата } sp0,ss0, { указатель стека кольца 0 } sp1,ss1, { указатель стека кольца 1 } sp2,ss2, { указатель стека кольца 2 } ip,flags,ax,cx,dx,bx,sp,bp, { регистры } si,di,es,cs,ss,ds,ldtr { микропроцессора } :word; end; {--------------Структура TSS для МП 80386 и выше--------------} t_tss_386=record link, { селектор возврата } esp0,ss0, { указатель стека кольца 0 } esp1,ss1, { указатель стека кольца 1 } esp2,ss2, { указатель стека кольца 2 } cr3,eip,eflags,eax,ecx,edx,ebx, { регистры } esp,ebp,esi,edi,es,cs,ss,ds,fs,gs,ldtr{ МП } :longint; bit_t, { бит ловушки задачи } adr_BKVV:word; { смещение БКВВ } Sys_inf, { поле для системной информации } BKVV:longint; { БКВВ } byte_end:byte; { байт завершения TSS } end; var gdt:array[0..15] of t_gdt; { Таблица GDT } idt:array[0..$32] of t_idt; { Таблица IDT } gdtr, { Содержимое GDTR } idtr, { Содержимое IDTR для работы в защищенном режиме } idtr_r { Содержимое IDTR для работы в реальном режиме } :t_dtr; ofs_ret, { Смещение и } sel_ret, { селектор точки возврата в реальный режим } ofs_ret_mov, { Смещение метки ret_mov: } cs_prot, { Селектор регистра CS в защищенном режиме } cs1, { Значение сегмента кода модуля PROT } { Переменные для хранения значений регистров: } real_ss, { SS, } real_es, { ES и } real_sp:word; { SP } scan, { Скан-код нажатия клавиши } cpu_type, { Номер типа микропроцессора } res, { Признак сброса МП } rm1, { Содержимое регистров маски 1-го } rm2, { и 2-го контроллеров прерывания } excep, { Номер исключения } acc_int, { Байт доступа прерывания } acc_trap, { Байт доступа ловушки } t:byte; { Признак разрядности МП: T=0 - 16; T=8 - 32 } function lin_adr(seg,off:word):longint; function hex(p:longint):string; function hw(p:word):string; procedure init_gdt(i:byte;limit,base:longint;acces, procedure init_idt(i:byte;p_off,p_sel:word;acces:byte); procedure pic(mode:byte); procedure init_gdtr; procedure init_idtr_p; procedure init_idtr_r; procedure save_ret_real(seg,ofs:word;byte_shut:byte); procedure not_int; procedure en_int; procedure set_unr(base,limit:longint;kseg,byte_6h:byte); procedure save_sreg; procedure reset; procedure test_wr; procedure init_tss_286 (var tss:t_tss_286; cs,ds,es, ofs_task,ofs_task_stack,flags:word); procedure init_tss_386 (var tss:t_tss_386; cs,ds,es, ofs_task,ofs_task_stack,eflags:word); procedure get_cpu_type(inf:byte;var cpu:byte); procedure exc_00; procedure exc_01; procedure exc_02; procedure exc_03; procedure exc_04; procedure exc_05; procedure exc_06; procedure exc_07; procedure exc_08; procedure exc_10; procedure exc_11; procedure exc_12; procedure exc_13; procedure exc_14; procedure exc_16; procedure exc_17; procedure exc_18; procedure PIC_1; procedure PIC_2; procedure keyb; procedure int_30h; procedure int_30hr; procedure int_32h; implementation {------Преобразование логического адреса в линейный адрес-----} function lin_adr; begin lin_adr:=longint(seg) shl 4+off end;{lin_adr} {-------------Преобразование данных в 16-ричную форму---------} function hex(p:longint):string; var s:string; begin s:='h'; repeat s:=hex_tabl[p and $f]+s; p:=p shr 4 until p=0; hex:=s end;{hex} function hw(p:word):string; var i:byte; s:string; begin s:=''; for i:=0 to 3 do begin s:=hex_tabl[p and $f]+s; p:=p shr 4 end; hw:=s end;{hw} {------------Формирование дескриптора таблицы GDT-------------} procedure init_gdt(i:byte;limit,base:longint;acces, byte_6h:byte); begin with gdt[i] do begin lim_l :=limit; base_l :=base; base_h :=base shr 16; acc :=acces; lim_h :=limit shr 16 or byte_6h; base_hh:=base shr 24; end end; {init_gdt} {------Формирование данных регистра GDTR и его загрузка-------} procedure init_gdtr; begin gdtr.lim:=sizeof(gdt)-1; gdtr.base:=lin_adr(seg(gdt),ofs(gdt)); asm db 0fh,01h,16h { LGDT gdtr: } dw gdtr { загрузка атрибутов GDT в GDTR из gdtr } end end; {init_gdtr} {------------Формирование дескриптора таблицы IDT-------------} procedure init_idt(i:byte;p_off,p_sel:word;acces:byte); begin with idt[i] do begin off_l:=p_off; sel:=p_sel; par:=0; acc:=acces; off_h:=0 end end; {init_idt} {--------Сохрание и формирование данных регистра IDTR---------} {--------и его загрузка для работы в защищенном режиме--------} procedure init_idtr_p; begin asm db 0fh,1,0eh { SIDT idtr: } dw idtr_r { Сохранение атрибутов IDT в idtr_r } end; idtr.lim:=sizeof(idt)-1; idtr.base:=lin_adr(seg(idt),ofs(idt)); asm db 0fh,01h,1eh { LIDT idtr: } dw idtr { Загрузка атрибутов IDT в IDTR из idtr } end; end;{init_idtr_p} {------Формирование данных регистра IDTR и его загрузка-------} {----------------для работы в реальном режиме-----------------} procedure init_idtr_r; begin idtr_r.lim:=$3ff; { размер таблицы векторов, } idtr_r.base:=0; { базовый адрес таблицы векторов } end;{init_idtr_r} {-------------Формирование данных для возврата----------------} {-------------в реальлный режим после сброса МП---------------} procedure save_ret_real; begin {-------------Сохранение значений регистров маски-------------} {-------------1-го и 2-го контроллеров прерываний-------------} rm1:=port[$21]; rm2:=port[$a1]; {---------Занесение в ячейки 40h:67h и 40h:69h адреса---------} {------(смещение и сегмент) точки возврата в реальный режим---} {-------------------после сброса МП---------------------------} memw[$40:$67]:=ofs; memw[$40:$69]:=seg; {--------Занесение в ячейку КМОП памяти с адресом 0Fh---------} {-----------байта состояния отключения (byte_shut).-----------} {-------Значение Ah этого байта обеспечивает при сбросе МП----} {---------переход по адресу в ячейках 40h:67h и 40h:69h;------} {----код 5 помимо этого осуществляет также инициализацию------} {----------------контроллеров прерываний----------------------} port[$70]:=$0f; port[$71]:=byte_shut; end;{save_ret_real} {----------------Запрет аппаратных прерываний-----------------} procedure not_int; begin asm cli end; { маскируемых } port[$70]:=$80; { и немаскируемых } end; {not_int} {---------------Разрешение аппаратных прерываний--------------} procedure en_int; begin asm sti end; { маскируемых } port[$70]:=$d; { и немаскируемых } mem[$40:$17]:=0 { Сброс состояния клавиш-переключателей } end; {en_int} {------------------Установка режима "Unreal"------------------} procedure set_unr(base,limit:longint;kseg,byte_6h:byte); begin { Формирование таблицы GDT: } init_gdt(0,0,0,0,0); { нуль-дескриптор } init_gdt(1,limit,base,$92,$80); { дескриптор сегмента } init_gdtr; { Создание данных и загрузка регистра GDTR } not_int;{ Запрет маскируемых и немаскируемых прерываний } asm { Переход в защищенный режим: } db $0f,$20,0c0h { MOV EAX,CR0 } db 66h,0dh { OR EAX,1 } dd 1h db $0f,22h,0c0h { MOV CR0,EAX } { Загрузка селектора заданного сегмента (kseg): } mov ax,8 cmp kseg,0 jnz @3 db 8eh,0c0h { MOV ES,AX } jmp @k @3: cmp kseg,3 db 8eh,0d8h { MOV DS,AX } jmp @k @4: cmp kseg,4 jnz @5 db 8eh,0e0h { MOV FS,AX } jmp @k @5:db 8eh,0e8h { MOV GS,AX } { Возврат в реальный режим: } @k:db 0fh,20h,0c0h { MOV EAX,CR0 } db 66h,25h { AND EAX,FFFFFFFEh } dd 0fffffffeh db 0fh,22h,0c0h { MOV CR0,EAX } end; en_int end; {------------Программирование ведущего и ведомого-------------} {-------------контроллеров прерываний для работы-------------} {------в реальном (mode=0) и защищенном (mode=1) режимах------} procedure pic(mode:byte); var k1,k2:byte; begin if mode=0 then begin k1:=8; k2:=$70 end else begin k1:=$20; k2:=$28 end; port[$20]:=$11; { 1-й ПКП: ICW1 } port[$21]:=k1; { 1-й ПКП: ICW2 } port[$21]:=4; { 1-й ПКП: ICW3 } port[$21]:=1; { 1-й ПКП: ICW4 } port[$a0]:=$11; { 2-й ПКП: ICW1 } port[$a1]:=k2; { 2-й ПКП: ICW2 } port[$a1]:=2; { 2-й ПКП: ICW3 } port[$a1]:=1; { 2-й ПКП: ICW4 } end;{pic} {----------Сохранение значений сегментных регистров-----------} procedure save_sreg; begin memw[0:4*$60]:=Dseg; { DS, } real_ss:=Sseg; { SS и } asm mov real_es,es end { ES } end;{save_sreg} {-------------Возврат в реальный режим по команде-------------} {--------контроллера клавиатуры, выполняющей сброс МП---------} procedure reset;assembler; asm mov res,1 { Установка признака сброса МП } mov al,0feh { Команда сброса } out 64h,al { микропроцессора } @wait_res: { Ожидание во время сброса МП } hlt jmp @wait_res db 0cbh { Межсегментный возврат } end; {reset} {---Проверка сохранения запрета записи в сегмент кода после---} {------возврата МП из защищенного режима по команде MOV:------} {-----если запрет сохранен - вырабатывается прерывание 13,----} {-----обработчик которого (процедура reset) сбрасывает МП-----} procedure test_wr; begin Meml[0:13*4]:=Longint(@reset); { Занесение адреса } { обработчика прерывания 13 - процедуры reset } { в область векторов } asm (* db 2eh { CS: }*) mov ax,cs:[0] (* db 2eh *) mov cs:[0],ax { Запись в сегмент кода } end; pic(0); { Программирование ПКП для реального режима } end; {test_wr} {-----------------Формирование TSS для 80286------------------} procedure init_tss_286 (var tss:t_tss_286; cs,ds,es, ofs_task,ofs_task_stack,flags:word); begin tss.cs:=cs; tss.ds:=ds; tss.es:=es; tss.ss:=ds; tss.ip:=ofs_task; tss.bp:=ofs_task_stack; tss.sp:=ofs_task_stack; tss.ldtr:=0; tss.flags:=flags; end;{init_tss_286} {--------------Формирование TSS для 80386 и выше--------------} procedure init_tss_386(var tss:t_tss_386; cs,ds,es, ofs_task,ofs_task_stack,eflags:word); begin tss.cs:=cs; tss.ds:=ds; tss.es:=es; tss.ss:=ds; tss.eip:=ofs_task; tss.ebp:=ofs_task_stack; tss.esp:=ofs_task_stack; tss.ldtr:=0; tss.eflags:=eflags; tss.bit_t:=0; tss.adr_bkvv:=108; tss.BKVV:=0; tss.byte_end:=$ff end;{init_tss_386} {---------Определение типа микропроцессора (cpu_type)---------} procedure get_cpu_type(inf:byte;var cpu:byte); var data_cach:array[1..4,1..4] of byte; { Данные о кэше МП } max_inp, { Max значение вх. параметра команды CPUID } EBX_, { Брэнд ID и др. } feature, { Данные об особенностях МП (регiстр EDX) } ECX_:longint; { Данные об особенностях МП (регiстр ECX) } desc_L2:word; { Дескриптор кэша L2 } { Серийный номер микропроцессора: } sn_1, { младшие 32 разряда, } sn_2, { средние 32 разряда, } sn_3:longint; { старшие 32 разряда } vend:array[1..12] of char;{ Название фирмы-изготовителя } brand_str:array[1..48] of char; { Брэнд-строка } typ, { Тип МП (0-2) } model, { Модель МП (4-6) } i,j, id_flag, { Флаг исполнения МП команды CPUID } cpu_type, { Возвращаемый номер типа МП (0, 2-6) } brand, { Брэнд ID } CLFSH, { Длина строки кэша } NMP, { Число логических процессоров в кристалле } par:byte; { Число параметров команды CPUID } unknown:boolean; { Признак нераспознавания типа МП } s:string; begin unknown:=false; id_flag:=0; asm pushf { Сохранить FLAGS } @8086: { Проверка МП i8086: } { биты 12-15 регистра FLAGS всегда установлены } pushf pop ax mov cx,ax and ax,0fffh push ax popf pushf pop ax and ax,0f000h cmp ax,0f000h mov cpu_type,0 { Микропроцессор: 8086 } jne @80286 @80286: { Проверка МП i80286: } { биты 12-15 регистра FLAGS в реальном режиме всегда сброшены } or cx,0f000h push cx popf pushf pop ax and ax,0f000h mov cpu_type,2 { Микропроцессор: 80286 } jnz @80386 jmp @end_cpuid @80386: { Проверка МП i80386: } { флаг AC (бит 18) регистра EFLAGS не может быть установлен } db 66h { префикс разрядности: 32 разряда } pushf db 66h pop ax { Занести в EAX исходное значение EFLAGS } db 66h mov cx,ax { Сохранить исходное значение EFLAGS в ECX } db 66h,35h { Изменить командой XOR бит AC в EFLAGS } dd 040000h db 66h push ax { Сохранить новое значение EFLAGS в стеке } db 66h popf { Заменить текущее значение EFLAGS } db 66h pushf db 66h pop ax { Запомнить новое значение EFLAGS в EAX } db 66h xor ax,cx mov cpu_type,3 jz @end_cpuid { Если бит AC не меняется: } db 66h { микропроцессор: 80386 } push cx db 66h popf { Восстановить AC бит в EFLAGS } @80486: { Проверка МП i486 и последующих моделей: } { установка/сброс ID флага (бит 21) в EFLAGS } { указывает на выполнимость команды CPUID на данном МП } mov cpu_type,4 { Микропроцессор: i486 } db 66h mov ax,cx { Получить исходное значение EFLAGS } db 66h,35h { Изменить командой XOR бит ID в EFLAGS } dd 200000h db 66h push ax { Сохранить новое значение в стеке } db 66h popf { Занести новое значение в EFLAGS } db 66h pushf { Записать его в стек } db 66h pop ax { Переписать в EAX } popf { Восстановить EFLAGS } db 66h xor ax,cx { Если бит ID не меняется: } je @end_cpuid { МП не поддерживает команду CPUID } { Выполнение команды CPUID для определения } { фирмы, семейства, модели микропроцессора } mov id_flag,1 { Установка флага } { выполнения МП команды CPUID } db 66h xor ax,ax { Параметр для CPUID: EAX=0 } db 0fh,0a2h { Команда CPUID } db 66h mov ss:[bp+offset vend],bx { Из регистров EBX, } db 66h { EDX } mov ss:[bp+offset vend+4],dx { и ECX } db 66h { в переменную vend } mov ss:[bp+offset vend+8],cx { заносится имя фирмы } cmp al,1 { В AL - наибольшее значение параметра CPUID } jl @end_cpuid mov par,al db 66h xor ax,ax db 66h inc ax { Установка параметра CPUID =1 } db 0fh,0a2h { Команда CPUID: в AL - сигнатура МП } db 66h { В sn_3 - старшие 32 разряда } mov word ptr sn_3,ax { серийного номера МП } mov word ptr EBX_,bx { В EBX_- Brand ID и др. } db 66h mov word ptr ECX_,cx { В EСX_- особенности МП } db 66h mov word ptr feature,dx { В EDX_- особенности МП } mov cx,ax and ax,0f0h db 0c1h,0e8h,4 { Сдвиг в AX на 4 разряда вправо } mov model, al { В AL - модель МП } mov ax,cx and ax,0f00h db 0c1h,0e8h,8 { Сдвиг в AX на 8 разрядов вправо } mov cpu_type, al { В AL - номер семейства МП } mov ax,cx and ax,3000h db 0c1h,0e8h,12 { Сдвиг в AX на 12 разрядов вправо } mov typ, al { В AL - номер типа МП } db 66h mov word ptr feature,dx { В feature - особенности МП } cmp par,1 jz @end_cpuid db 66h,0b8h { MOV EAX,2: установка параметра } dd 2 { команды CPUID =2 } db 0fh,0a2h { Команда CPUID } db 66h mov ss:[bp+offset data_cach],ax { В регистрах EAX, } db 66h { EBX, ECX } mov ss:[bp+offset data_cach+4],bx { и EDX - } db 66h { информация о } mov ss:[bp+offset data_cach+8],cx { кэш-памяти МП, } db 66h { которая заносится в массив } mov ss:[bp+offset data_cach+12],dx { data_cach } @end_cpuid: end; s:=''; clrscr; if id_flag=0 then begin { Определение типа МП } case cpu_type of { без использования команды CPUID } 0:s:='i8086'; 2:s:='i80286'; 3:s:='i80386'; 4:s:='i486'; end; writeln(s); end else begin brand:=EBX_; { Значение брэнд ID } for i:=1 to 4 do { Определение дескриптора } for j:=1 to 4 do { кэша второго уровня } if data_cach[i,4] and 128=0 then if (data_cach[i,j]=$41) or (data_cach[i,j]=$42) or (data_cach[i,j]=$43) or (data_cach[i,j]=$44) or (data_cach[i,j]=$45) then begin desc_L2:=data_cach[i,j]; break end; case cpu_type of 4:case model of 0,1:s:='i486 DX'; 2:s:='i486 SX'; 3:s:='iDX2'; 4:s:='i486 SL'; 5:s:='iSX2'; 7:s:='iDX2 WB'; 8:if typ=0 then s:='iiDX4' else s:='iDX4 OverDrive'; 9:s:='AMD DX4'; 14:s:='Am5x86 в режиме WT'; 15:s:='Am5x86 в режиме WB'; else unknown:=true end; 5: if vend='GenuineIntel' then case model of 1:if typ=0 then s:='Pentium (60,66)' else s:='Pentium OverDrive (60,66)'; 2:if typ=0 then s:='Pentium (75..200)' else s:='Pentium OverDrive (75..133)'; 3:s:='Pentium OverDrive для 486'; 4:if typ=0 then s:='Pentium MMX (166,200)' else s:='Pentium MMX OverDrive (75..133)'; end else if vend='AuthenticAMD' then case model of 0:s:='AMD-K-PR75,90,100'; 1:s:='AMD-K-PR120,133'; 2:s:='AMD-K-PR120,166'; end; 6: case model of 1:s:='Pentium Pro'; 3:if typ=0 then s:='Pentium II модель 3' else s:='Pentium II OverDrive'; 5:case desc_L2 of $41:s:='Celeron модель 5'; $43:s:='Pentium II модель 5'; $44:s:='Pentium II Xeon модель 5'; end; 6:s:='Celeron модель 6'; 7:case desc_L2 of $43: s:='Pentium III модель 7'; $44,$45:s:='Pentium III Xeon модель 7'; end; 8:case brand of 1:s:='Celeron модель 8'; 2:s:='Pentium III модель 8'; 3: if sn_3=$6B1 then s:='Celeron модель 8' else s:='Pentium III Xeon модель 8'; 4: s:='Pentium III модель 8'; 6: s:='Мобильный Pentium III-M модель 8'; 7: s:='Мобильный Celeron модель 8'; end; $A:s:='Pentium III Xeon модель A'; $B:s:='Pentium III Xeon модель B'; else unknown:=true end; $F:case model of 0: begin s:='0.18-микронный '; case brand of 8: s:=s+'Pentium 4'; 9: s:=s+'Pentium 4'; $B: s:=s+'Xeon'; end; end; 1: begin s:='0.18-микронный '; case brand of 8: s :=s+'Pentium 4'; 9: s:=s+'Pentium 4'; $A: s:=s+'Celeron'; $B: if sn_3<$F13 then s:=s+'Xeon MP' else s:=s+'Xeon'; $C: s:=s+'Xeon MP'; $E: s:=s+'Xeon'; end; end; 2: begin s:='0.13-микронный '; case brand of 8: s:=s+'Pentium 4'; 9: s:=s+'Pentium 4'; $A: s:=s+'Celeron'; $B: if sn_3<$F13 then s:=s+'Xeon MP' else s:=s+'Xeon'; $C: s:=s+'Xeon MP'; $E: if sn_3<$F13 then s:=s+'Xeon' else s:=s+'мобильный Pentium 4-M'; $F: s:=s+'мобильный Celeron'; end end end {else unknown:=true} end; for i:=1 to 12 do write(vend[i]); if not unknown then writeln(' ',s) else writeln('МП сiмейства - ',cpu_type, ' модель - ',model); asm db 66h,0b8h dd 80000000h { MOV EAX,80000000h } db 0fh,0a2h { CPUID } db 66h mov word ptr max_inp,ax end; if max_inp>$80000000 then begin asm db 66h,0b8h { MOV EAX,80000002h } dd 80000002h db 0fh,0a2h { CPUID } db 66h mov ss:[bp+offset brand_str],ax { Из pегистpов EAX, } db 66h mov ss:[bp+offset brand_str+4],bx { EBX, } db 66h mov ss:[bp+offset brand_str+8],cx { ECX } db 66h mov ss:[bp+offset brand_str+12],dx { и EDX } {в переменную brand_str заносятся первые 12 символов бренд-строки} db 66h,0b8h dd 80000003h { MOV EAX,80000003h } db 0fh,0a2h { CPUID } db 66h mov ss:[bp+offset brand_str+16],ax db 66h mov ss:[bp+offset brand_str+20],bx db 66h mov ss:[bp+offset brand_str+24],cx db 66h mov ss:[bp+offset brand_str+28],dx db 66h,0b8h { MOV EAX,80000004h } dd 80000004h db 0fh,0a2h { CPUID } db 66h mov ss:[bp+offset brand_str+32],ax db 66h mov ss:[bp+offset brand_str+36],bx db 66h mov ss:[bp+offset brand_str+40],cx db 66h mov ss:[bp+offset brand_str+44],dx end; for i:=1 to 48 do write(brand_str[i]); writeln; end; if inf<>0 then begin writeln('Особенности микропроцессора:'); for i:=0 to 21 do if not ((i=10) or (i=20) or (i=28)) then begin s:=''; case i of 0:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'содержит FPU'; end; 1:begin if (feature shr i) and 1=0 then s:='не '; s:='поддерживает расширения для режима '; s:=s+'виртуального 8086'; end; 2:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает рассширенную отладку и CR4.DE'; end; 3:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает страницы 4 МБ'; end; 4:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команду RDTSC и CR4.TSD'; end; 5:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команды RDMSR и WRMSR'; end; 6:begin if (feature shr i) and 1=0 then s:='не '; s:='поддерживает расширение физического адреса'; s:=s+' и CR4.PAE'; end; 7:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает исключение 18 (MCE) и CR4.MCE'; end; 8:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команду CMPXCHG8B'; end; 9:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'содержит APIC'; end; 11:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команды SYSENTER и SYSEXIT'; end; 12:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает регистры MTRR'; end; 13:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает глобальные страницы и CR4.PGE'; end; 14:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает MCA и регистр MCG_CAP'; end; 15:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команды CMOV, FCMOV и FCOMI'; end; 16:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает таблицу атрибутов страниц PAT'; end; 17:begin if (feature shr i) and 1=0 then s:='не '; s:=s+ 'поддерживает 4 Мб страницы и адреса более 4 Гб'; end; 18:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает 96-разрядный серийный номер МП'; end; 19:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команду CLFLUSH'; end; 21:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает запись истории переходов'; end; end; writeln(' ',s); end; readkey; clrscr; writeln('Особенности микропроцессора:'); for i:=22 to 31 do if i<>30 then begin s:=''; case i of 22:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает программный контроль частоты МП'; end; 23:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает MMX команды'; end; 24:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команды FXSAVE и FXRSTOR'; end; 25:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команды SSE'; end; 26:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает команды SSE2'; end; 27:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает разрешение конфликтов памятi'; end; 28:begin if (feature shr i) and 1=0 then s:='не '; s:=s+' поддерживает логические процессоры и HT'; end; 29:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'поддерживает температурный мониторинг'; end; 31:begin if (feature shr i) and 1=0 then s:='не '; s:=s+'пiдтриму переривання по FERR'; end; end; writeln(' ',s); end; readkey; clrscr; if par>1 then begin writeln('Число повторений команды CPUID с EAX=2 - ', data_cach[1,1]); writeln('МП имеет следующие блоки кэш-памяти:'); writeln; for i:=1 to 4 do for j:=1 to 4 do if (i<>1) or (j<>1) then if data_cach[i,4] and 128=0 then begin s:=''; if data_cach[i,j]<>0 then begin case data_cach[i,j] of 1:s:='TLB команд: 4 Кб страницы, 4-напр., 32 входа'; 2:s:='TLB команд: 4 Мб стран., полностью ассоц., 2 входа'; 3:s:='TLB данных: 4 Кб страницы, 4-напр., 64 входа'; 4:s:='TLB данных: 4 Мб страницы, 4-напр., 8 входов'; 6:s:='Кэш команд: 8 Кб, 4-напр., строка 32 байта'; 8:s:='Кэш команд: 16 Кб, 4-напр., строка 32 байта'; $A:s:='Кэш данных: 8 Кб, 2-напр., строка 32 байта'; $C:s:='Кэш данных: 16 Кб, 4-напр., строка 32 байта'; $22:s:=' Объедин. кэш L3: 512 Кб, 4-напр., строка 64 байта'; $23:s:=' Объедин. кэш L3: 1 Мб, 8-напр., строка 64 байта'; $25:s:=' Объедин. кэш L3: 2 Мб, 8-напр., строка 64 байта'; $29:s:=' Объедин. кэш L3: 4 Мб, 8-напр., строка 64 байта'; $39:s:='Объедин. кэш L2: 128 Кб, 4-напр., строка 64 байта'; $3B:s:='Объедин. кэш L2: 128 Кб, 2-напр., строка 64 байта'; $3C:s:='Объедин. кэш L2: 256 Кб, 4-напр., строка 64 байта'; $40:if cpu_type=6 then s:='Кэш L2: не содержится' else if cpu_type=$f then s:='Кэш L3: не содержится'; $40:s:='Нет кэша L2 (семейство P6) или L3 (Pentium 4)'; $41:s:='Объедин. кэш: 128 Кб, 4-напр., строка 32 байта'; $42:s:='Объедин. кэш: 256 Кб, 4-напр., строка 32 байта'; $43:s:='Объедин. кэш: 512 Кб, 4-напр., строка 32 байта'; $44:s:='Объедин. кэш: 1 Мб, 4-напр., строка 32 байта'; $45:s:='Объедин. кэш: 2 Мб, 4-напр., строка 32 байта'; $50:begin s:='TLB команд: 4 Кб,2 Мб или 4 Мб страницы,'; s:=s+'полностью ассоц., 64 входа'; end; $51:begin s:='TLB команд: 4 Кб, 2 Мб або 4 Мб страницы,'; s:=s+'полностью ассоц., 128 входов'; end; $52:begin s:='TLB команд: 4 Кб, 2 Мб або 4 Мб страницы,'; s:=s+'полностью ассоц., 256 входов'; end; $5b:begin s:='TLB данных: 4 Кб или 4 Мб страницы.,'; s:=s+'полностью ассоц., 64 входа'; end; $5C:begin s:='TLB команд: 4 Кб або 4 Мб страницы.,'; s:=s+'полностью ассоц., 128 входов'; end; $5D:begin s:='TLB команд: 4 Кб або 4 Мб страницы.,'; s:=s+'полностью ассоц., 256 входов'; end; $66:s:='Кэш данных секторный:8 Кб, 4-напр., строка 64 байта'; $67:s:='Кэш данных секторный: 16 Кб, 4-напр., строка 64 байти'; $68:s:='Кэш данных секторный: 32 Кб, 4-напр., строка 64 байти'; $70:s:='Кэш трас команд: 12 К микроинструкций, 4-напр.'; $71:s:='Кэш трас команд: 16 К микроинструкций, 8-напр. '; $72:s:='Кэш трас команд: 32 К микроинструкций, 8-напр. '; $79:begin s:='Объедин. кэш секторный: 128 Кб, 8-напр.,'; s:=s+' строка 64 байта' end; $7A:begin s:='Объедин. кэш секторный: 256 Кб, 8-напр.,'; s:=s+' строка 64 байта' end; $7B:begin s:='Объедин. кэш секторный: 512 Кб, 8-напр.,'; s:=s+' строка 64 байта' end; $7C:begin s:='Объедин. кэш секторный: 1 Мб, 8-напр.,'; s:=s+' строка 64 байта' end; $82:s:='Объедин. кэш: 256 Кб, 8-напр., строка 32 байта'; $83:s:='Объедин. кэш: 512 Кб, 8-напр., рядок 32 байти'; $84:s:='Объедин. кэш: 1 Мб, 8-напр., строка 32 байта'; $85:s:='Объедин. кэш: 2 Мб, 8-напр., строка 32 байта'; else begin write(' Дескриптор: ',hex(data_cach[i,j])); s:='' end end; writeln(' ',s); end end end; if (feature shr 18) and 1<>0 then begin asm db 66h,0b8h { MOV EAX,3 } dd 3 { CPUID с параметром 3: определение } db 0fh,0a2h { серийного номера микропроцессора } db 66h { В sn_2 - средние 32 разряда } mov word ptr sn_2,dx { серийного номера МП } db 66h { В sn_1 - младшие 32 разряда } mov word ptr sn_1,cx { серийного номера МП } end; writeln('Серийный номер микропроцессора: ', hw(sn_3 shr 16),'-',hw(word(sn_3)),'-', hw(sn_2 shr 16),'-',hw(word(sn_2)),'-', hw(sn_1 shr 16),'-',hw(word(sn_1))); end; end end; asm { Возврат значения параметра cpu: } mov bx,ss:[bp+offset cpu] { В BX - адрес cpu } mov al,cpu_type mov [bx],al end; end; {get_cpu_type} {--------Обработчики исключений 0-18 (exc_00-exc_18)----------} {------------выводят на экран номер исключения----------------} {--------и осуществляют переход в реальный режим:-------------} procedure exc_00;assembler; { Обработчик исключения 0: } asm { деление на 0 } mov excep,0 int 32h { Вывод номера исключения } cmp cpu_type,2 jz @1 db 0ffh,2eh { Межсегментный переход } dw ofs_ret_mov { на метку ret_mov: } @1:db 9ah { Межсегментный вызов } dw offset reset { процедуры сброса МП reset } dw code_sel2 { с переходом на метку ret_r } end; procedure exc_01;assembler; { Обработчик исключения 1: } asm { - при TF=1 регистра EFLAGS; } mov excep,1 { - при T=1 сегмента TSS; } int 32h { - по контрольным точкам программы; } cmp cpu_type,2 { - по контрольным точкам данных; } jz @1 { - по контрольным точкам УВВ; } db 0ffh,2eh { - при защите регистров отладки } dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_02;assembler; { Обработчик исключения 2: } asm { немаскируемое прерывание (NMI) } mov excep,2 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_03;assembler; { Обработчик исключения 3: } asm { по команде INT 3 } mov excep,3 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_04;assembler; { Обработчик исключения 4: } asm { по команде INTO при OF=1 } mov excep,4 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_05;assembler; { Обработчик исключения 5: } asm { выход за пределы диапазона } mov excep,5 { при выполнении команды BOUND } int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_06;assembler; { Обработчик исключения 6: } asm { неверный код операции } mov excep,6 { или адресации } int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_07;assembler; { Обработчик исключения 7: } asm { недоступно устройство FPU } mov excep,7 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_08;assembler; { Обработчик исключения 8: } asm { двойная ошибка } mov excep,8 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_10;assembler; { Обработчик исключения 10: } asm { недоступен TSS } mov excep,10 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_11;assembler; { Обработчик исключения 11: } asm { недоступен сегмент } mov excep,11 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_12;assembler; { Обработчик исключения 12: } asm { ошибка доступа к сегменту стека } mov excep,12 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_13;assembler; { Обработчик исключения 13: } asm { нарушение общей защиты } mov excep,13 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_14;assembler; { Обработчик исключения 14: } asm { недоступна страница } mov excep,14 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_16;assembler; { Обработчик исключения 16: } asm { ошибка FPU при NE=1 регистра CR0 } mov excep,16 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_17;assembler; { Обработчик исключения 17: } asm { ошибка выравнивания данных } mov excep,17 int 32h cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; procedure exc_18;assembler; { Обработчик исключения 18: } asm { ошибка функционирования узлов МП и МПС } mov excep,18 cmp cpu_type,2 jz @1 db 0ffh,2eh dw ofs_ret_mov @1:db 9ah dw offset reset dw code_sel2 end; {---------Обработчики-заглушки аппаратных прерываний,---------} {----------поступающих на 1-й контроллер прерываний-----------} procedure PIC_1;assembler; asm push ax mov al,$20 out $20,al { Сброс бита регистра ISR 1-го ПКП } pop ax cmp cpu_type,2 { Если 80286 - разрядность 16, } je @7 { иначе - 32 } db 66h @7:iret end; {---------Обработчики-заглушки аппаратных прерываний,---------} {----------поступающих на 2-й контроллер прерываний-----------} procedure PIC_2;assembler; asm push ax mov al,$20 { Сброс бита регистра ISR } out $20,al { 1-го и } out $a0,al { и 2-го контроллеров прерываний } pop ax cmp cpu_type,2 je @8 db 66h @8:iret end; procedure keyb;assembler; { Обработчик прерываний } asm { от клавиатуры: } mov al,20h out 20h,al in al,60h { Чтение скан-кода нажатия/отжатия клавиши } test al,$80 jnz @k1 { Переход, если клавиша отжата } mov scan,al @k1:cmp cpu_type,2 je @k2 db 66h @k2:iret end; procedure int_30h;assembler; { Обработчик программного } asm { прерывания 30h: } cmp ah,2 { AH - номер функции } jz @i2 { Al - номер подфункции } cmp ah,3 { BL - номер строки экрана } jz @i3 { BH - номер столбца экрана } cmp ah,4 { DL/DX/EDX - значение данных } jz @i4 { (байта/слова/двойного слова) } cmp ah,5 { CL - видео-атрибут } jz @i5 { SI - смещение строки символов } { Функция 1: установка маркера в заданную точку экрана } mov ax,bx xor bh,bh mov bl,ah xor ah,ah mov dl,80 mul dl add ax,bx shl ax,1 mov di,ax jmp @end @i2: { Функция 2: вывод символа на экран } mov al,dl mov ah,cl stosw jmp @end @i3: { Функция 3: вывод данных на экран в 16-ричной форме } { AL=0 - вывод байта } { AL=1 -вывод слова } { AL=2 - вывод двойного слова } lea bx,hex_tabl mov ah,cl cmp al,0 jz @8 cmp al,1 jz @16 add di,14 mov cx,8 jmp @1 @8:add di,2 mov cx,2 jmp @1 @16:add di,6 mov cx,4 @1:push cx @lp:mov al,dl and al,0fh db 66h shr dx,4 xlat stosw sub di,4 loop @lp pop cx shl cx,1 add cx,4 {2} add di,cx jmp @end @i4: { Функция 4: вывод строки символов на экран } mov ah,cl mov bx,si inc si mov cl,[bx] xor ch,ch @wxy: lodsb stosw loop @wxy jmp @end @i5: { Функция 5: вывод данных на экран в двоичной форме } { AL=0 - вывод байта }{ AL=1 -вывод слова } { AL=2 - вывод двойного слова } { lea bx,duo_tabl} mov ah,cl cmp al,0 jz @8_2 cmp al,1 jz @16_2 mov cx,8 jmp @2 @8_2: mov cx,2 jmp @2 @16_2: mov cx,4 @2:push cx push cx shl cx,3 sub cx,2 add di,cx { di+cx*8-2 } pop cx @lp_1:push cx xor ah,8 mov cx,4 @lp_2:mov al,dl and al,01h db 66h shr dx,1 xlat stosw sub di,4 loop @lp_2 pop cx loop @lp_1 pop cx shl cx,3 add cx,2 { di+cx*8+2 } add di,cx @end:db 66h iret end; procedure int_30hr;assembler; { Обработчик программного } asm { прерывания 30h: } cmp ah,2 { AH - номер функции } jz @i2 { Al - номер подфункции } cmp ah,3 { BL - номер строки экрана } jz @i3 { BH - номер столбца экрана } cmp ah,4 { DL/DX/EDX - значение данных } jz @i4 { (байта/слова/двойного слова) } cmp ah,5 { CL - видео-атрибут } jz @i5 { SI - смещение строки символов } { Функция 1: установка маркера в заданную точку экрана } mov ax,bx xor bh,bh mov bl,ah xor ah,ah mov dl,80 mul dl add ax,bx shl ax,1 mov di,ax jmp @end @i2: { Функция 2: вывод символа на экран } mov al,dl mov ah,cl stosw jmp @end @i3: { Функция 3: вывод данных на экран в 16-ричной форме } { AL=0 - вывод байта } { AL=1 -вывод слова } { AL=2 - вывод двойного слова } lea bx,hex_tabl mov ah,cl cmp al,0 jz @8 cmp al,1 jz @16 add di,14 mov cx,8 jmp @1 @8:add di,2 mov cx,2 jmp @1 @16:add di,6 mov cx,4 @1:push cx @lp:mov al,dl and al,0fh db 66h shr dx,4 xlat stosw sub di,4 loop @lp pop cx shl cx,1 add cx,4 {2} add di,cx jmp @end @i4: { Функция 4: вывод строки символов на экран } mov ah,cl mov bx,si inc si mov cl,[bx] xor ch,ch @wxy: lodsb stosw loop @wxy jmp @end @i5: { Функция 5: вывод данных на экран в двоичной форме } { AL=0 - вывод байта } { AL=1 -вывод слова } { AL=2 - вывод двойного слова } { lea bx,duo_tabl} mov ah,cl cmp al,0 jz @8_2 cmp al,1 jz @16_2 mov cx,8 jmp @2 @8_2: mov cx,2 jmp @2 @16_2: mov cx,4 @2:push cx push cx shl cx,3 sub cx,2 add di,cx { di+cx*8-2 } pop cx @lp_1:push cx xor ah,8 mov cx,4 @lp_2:mov al,dl and al,01h db 66h shr dx,1 xlat stosw sub di,4 loop @lp_2 pop cx loop @lp_1 pop cx shl cx,3 add cx,2 { di+cx*8+2 } add di,cx @end: iret end; {------------------Вывод номера исключения--------------------} procedure int_32h;assembler; asm mov ah,1 { Функция 1: установка маркера на экране } mov bl,22 { с координатами - строка 22, } mov bh,1 { столбец 1 } int 30h mov ah,4 { Функция 4: вывод на экран } mov si, offset s2 { строки символов s2 } mov cl,1ah { видеоатрибут } int 30h mov ax,300h { Функция 3, подфункция 0: } mov dl,excep { вывод на экран номера исключения } mov cl,1ch { видеоатрибут } int 30h db 66h iret end; end. (*16. а) Исключение, вызванное запретом чтения из сегмента кода б) Разработать обработчик прерывания от системного таймера, который каждые 5 секунд меняет цвет бордюра. I. Вызвать требуемое в индивидуальном задании исключение. II. Обработать это исключение одним из двух способов: а) устранив причину исключения; б) пропустив команду, вызвавшую исключение. III. Обработать заданное внешнее прерывание.*) program p_intr; { Обработка прерываний в защищенном режиме } uses crt, prot; { Модуль PROT содержит константы, } { типы переменных, переменные, процедуры и функции } { для работы в защищенном режиме } label ret_r; { Точка возврата в реальный режим } const s:string='Обработка исключений и прерываний в защищенном режиме'; s1:string='CS SS DS ES CR0 EFLAGS: '; s2:string='Обработано исключение '; s3:string='Na 5 tik timera menyaem cvet BORDURA.'; s4:string='Press Esc to exit'; var cs_real, { Значение регистра CS в реальном режиме } err, { Код ошибки } lim1,lim2,count:word; scan,i,al_,ah_,n_exc,row:byte; sscan:byte; eflags:longint; quel,counter,color:byte; dwd:word; {--------------Разработка обработчиков исключений--------------} procedure out_exc;assembler; { Вывод номера исключения } asm mov ah,1 { Функция 1: установка маркера на экране } mov bl,22 { с координатами - строка 22, } mov bh,1 { столбец 1 } int 30h mov ah,4 { Функция 4: вывод на экран } mov si, offset s2 { строки символов s2 } mov cl,1eh int 30h mov ax,300h { Функция 3, подфункция 0: } mov dl,excep { вывод на экран номера исключения } mov cl,1ch int 30h mov dx,dwd ret end; procedure exc_00;assembler; { Обработчик исключения 0 } {-----Два варианта устранения зацикливания обработки отказа----} mov bl,1 { Вариант 1: устранение причины отказа } pusha (* push bp { Вариант 2: изменение в стеке значения } mov bp,sp { счетчика команд IP на величину длины команды } inc word ptr [bp+2] pop bp *) mov excep,0 call out_exc; { Вывод сообщения об обработке исключения } popa cmp cpu_type,2 jz @2 db 66h @2:iret end; procedure exc_13;assembler; { Обработчик исключения 0 } {-----Два варианта устранения зацикливания обработки отказа----} asm cmp cpu_type,2 jz @1 db 66h @1:pop bx {-------------Вариант 2: изменяет в стеке значение------------} {-------------счетчика команд IP на длину команды,------------} {-----------вызвавшей исключение (div bl - 1 байт)------------} push bp mov bp,sp add word ptr [bp+2],4 { или inc word ptr [bp+2] } pop bp {---------------------Вывод сообщения-------------------------} {---------о возникновении исключения с номером excep----------} pusha mov excep,13 int 32h (*push bx mov ax,501h { Функция 5: вывод на экран } mov cl,1eh { кода ошибки в двоичной форме } pop dx int 30h *) popa {-------Вариант 3: выполняет выход из защищенного режима-------} {----через межсегментный косвенный переход на метку ret_mov----} (* db 0ffh,2eh dw ofs_ret_mov *) cmp cpu_type,2 jz @2 db 66h @2:iret end; procedure exc_0b;assembler; { Обработчик исключения 11 } { вызывается при отсутствии сегмента в памяти и выполняет } { коррекцию дескриптора сегмента - востанавливает бит P } asm mov excep,0bh cmp cpu_type,2 jz @1 db 66h @1:pop bx { Чтение из стека кода ошибки } mov err,bx { и запись в переменную err } and bx,not 7 { Выделение смещения селектора } add bx,offset gdt+5 { Выбор поля байта доступа в GDT } push ax mov al, [bx] { Чтение байта доступа сегмента } or al,80h mov [bx],al { Установка бита P=1 в байте доступа } pop ax cmp cpu_type,2 jz @2 db 66h @2:iret end; procedure keyb;assembler; { Обработчик прерываний } asm { от клавиатуры: } mov al,20h out 20h,al { Сброс контроллера прерываний } in al,60h { Чтение скан-кода нажатия/отжатия клавиши } test al,80h jnz @1 { Переход, если клавиша отжата } mov scan,al @1:cmp cpu_type,2 jz @3 db 66h @3:iret end; procedure ttim;assembler; { Обработчик прерываний } asm { от timer: } push ax mov al,$20 out $20,al { Сброс бита регистра ISR 1-го ПКП } pop ax inc counter cmp counter,5 jnz @99 mov counter,0 push dx push ax mov dx,3dah in al,dx mov dx,3c0h mov al,11h out dx,al inc color mov al,color out dx,al mov al,20h out dx,al pop dx pop ax @99:cmp cpu_type,2 { Если 80286 - разрядность 16, } jz @l1 { иначе - 32 } db 66h @l1:iret end; begin clrscr; {------Определение значения сегмента кода cs1 процедур,-----} {------------------описанных в модуле PROT------------------} cs1:=Seg(int_30h); excep:=$ff; { Отличное от FFh значение переменной excep } { означает номер возникшего при работе программы исключения } sscan:=0; { Клавиша не нажата } res:=0; { МП сброшен не был } {-----------Определение типа микропроцессора----------------} get_cpu_type(0,cpu_type); { В cpu_type - номер типа МП } if cpu_type=2 then t:=0 { 16-разрядный МП } else t:=8; { 32-разрядный МП } { Формирование байта доступа прерывания: } acc_int:=present OR type_int OR t; { Формирование байта доступа ловушки: } acc_trap:=present OR type_trap OR t; {-----------------Формирование таблицы GDT--------------------} { Нуль-дескриптор: } init_gdt(0,0,0,0,0); { Дескриптор первого сегмента кода: } init_gdt(1,$ffff,lin_adr(cseg,0),acc_code1,0); { Дескриптор второго сегмента кода: } init_gdt(2,$ffff,lin_adr(cs1,0),acc_code,0); { Дескриптор сегмента данных: } init_gdt(3,$ffff,lin_adr(dseg,0),acc_data,0); {--------Имитация отсутствия сегмента данных в памяти:--------} {-------------бит P в его дескрипторе равен нулю--------------} { gdt[3].acc:=gdt[3].acc and not present; { Дескриптор сегмента стека: } init_gdt(4,0,lin_adr(sseg,0),acc_stack,0); { Дескриптор сегмента видеопамяти: } init_gdt(5,4000-1,lin_adr($b800,0),acc_data,0); {------Формирование данных регистра GDTR и его загрузка-----} init_gdtr; {----Определение селектора (cs_real) и смещения (ofs_ret)---} {-------------точки возврата в реальный режим---------------} cs_real:=Cseg; asm mov ofs_ret,offset ret_r end; {---------------------Формирование данных-------------------} {---------для перехода на метку ret_r после сброса МП-------} {-----------с инициализацией контроллера прерываний---------} save_ret_real(cs_real,ofs_ret,5); {------Запрет маскируемых и немаскируемых прерываний--------} not_int; {--------------Формирование таблицы IDT-------------------- } { Дескрипторы шлюзов обработчиков исключений 0-18: } init_idt(0,ofs(exc_00),code_sel,acc_trap); init_idt(1,ofs(exc_01),code_sel2,acc_trap); init_idt(2,ofs(exc_02),code_sel2,acc_trap); init_idt(3,ofs(exc_03),code_sel2,acc_trap); init_idt(4,ofs(exc_04),code_sel2,acc_trap); init_idt(5,ofs(exc_05),code_sel2,acc_trap); init_idt(6,ofs(exc_06),code_sel2,acc_trap); init_idt(7,ofs(exc_07),code_sel2,acc_trap); init_idt(8,ofs(exc_08),code_sel2,acc_trap); init_idt(10,ofs(exc_10),code_sel2,acc_trap); init_idt(11,ofs(exc_0b),code_sel,acc_trap); init_idt(12,ofs(exc_12),code_sel2,acc_trap); init_idt(13,ofs(exc_13),code_sel,acc_trap); init_idt(14,ofs(exc_14),code_sel2,acc_trap); init_idt(16,ofs(exc_16),code_sel2,acc_trap); init_idt(17,ofs(exc_17),code_sel2,acc_trap); init_idt(18,ofs(exc_18),code_sel2,acc_trap); { Дескриптор шлюза обработчика прерывания от таймера: } init_idt($20,ofs(ttim),code_sel,acc_int); { Дескриптор шлюза обработчика прерывания от клавиатуры : } init_idt($21,ofs(keyb),code_sel,acc_int); { Дескрипторы шлюзов обработчиков прерываний IRQ2-IRQ7: } for i:=2 to 7 do init_idt($20+i,ofs(PIC_1),code_sel2,acc_int); { Дескрипторы шлюзов обработчиков прерываний IRQ8-IRQ15: } for i:=8 to 15 do init_idt($20+i,ofs(PIC_2),code_sel2,acc_int); { Дескриптор шлюза обработчика программного прерывания: } init_idt($30,ofs(int_30h),code_sel2,acc_trap); init_idt($32,ofs(int_32h),code_sel2,acc_int); {-------Сохрание данных регистра IDTR в переменной IDTR-----} asm db 0fh,1,0eh { SIDT idtr } dw idtr_r end; {------Формирование данных регистра IDTR и его загрузка-----} {--------------для работы в защищенном режиме---------------} init_idtr_p; (* {--------------Формирование данных регистра IDTR------------} {---------------для работы в реальном режиме---------------} init_idtr_r; *) {----------Программирование контроллера прерываний----------} {--------------для работы в защищенном режиме---------------} pic(1); {-------Сохранение содержимого регистров DS,SS,ES и SP------} save_sreg; real_sp:=SPtr; if cpu_type=2 then {---------Переход в защищенный режим для МП 80286-----------} asm { Установка бита PE=1 в регистре MSW: } db 0fh,01h,0e0h { SMSW AX } or ax,1 db 0fh,01h,0f0h { LMSW AX } end else {-------Переход в защищенный режим для МП 80386 и выше-----} asm { Установка бита PE=1 в регистре управления CR0: } db 0fh,20h,0c0h { MOV EAX,CR0 } db 66h,0dh { OR EAX,1 } dd 1h db 0fh,22h,0c0h { MOV CR0,EAX } end; asm push code_sel { Дальний переход на метку @prot } push offset @prot { для загрузки CS и сериализации } retf {----------------Работа в защищенном режиме-----------------} {---------------Загрузка сегментных регистров---------------} {---------------соответствующими селекторами----------------} @prot: mov ds,data_sel { DS, } mov ss,stack_sel { SS } mov es,video_sel { и ES } {-------------------Вывод на экран строки-------------------} {---------"Обработка прерываний в защищенном режиме"--------} {-----------с помощью функций 1 и 4 прерывания 30h----------} mov ah,1 { Установка маркера: } mov bx,903h { строка 3, столбец 9 } int 30h mov ah,4 { Вывод строки s на экран: } mov cl,1eh { видеоатрибут, } mov si,offset s { адрес строки } int $30 mov ah,1 mov bx,705h int 30h mov ah,4 { Функция 4: вывод на экран } mov si, offset s1 { строки символов s1 } mov cl,1ch int 30h mov ax,301h { Функция 3, подфункция 1: } mov dx,cs mov cl,1ch int 30h { Вывод на экран CS } mov ax,301h mov dx,ss mov cl,1ch { Вывод на экран SS } int 30h mov ax,301h mov dx,ds mov cl,1ch int 30h { Вывод на экран DS } mov ax,301h mov dx,es mov cl,1ch int 30h { Вывод на экран ES } mov ax,302h { Функция 3, подфункция 2: } db 0fh,20h,0c2h { MOV EDX,CR0 } mov cl,1ch int 30h { Вывод на экран CR0 } mov ax,302h db 66h pushf db 66h pop dx mov cl,1ch int 30h { Вывод на экран EFLAGF } mov ah,1 mov bx,510h int 30h mov ah,4 { Функция 4: вывод на экран } mov si, offset s3 { строки символов s3 } mov cl,1ch int 30h mov ah,1 mov bx,511h int 30h mov ah,4 { Функция 4: вывод на экран } mov si, offset s4 { строки символов s3 } mov cl,1ch int 30h {Virabotka zad isklucheniya} mov ax,cs:[0] {-------------Разрешение маскируемых прерываний-------------} sti {----Ожидание и обработка прерываний до установки семафора----} {mov ax,cs:[0]} @wait: cmp scan,1h jnz @wait {int 13} cmp cpu_type,2 jnz @mov {----Возврат в реальный режим по сбросу микропроцессора-----} push code_sel2 push offset reset retf {---Подготовка к возврату в реальный режим по команде MOV---} {---------Установка параметров сегментов DS, SS и ES--------} {---------------для работы в реальном режиме----------------} @mov: (* ARBEITEST an seleron 6 version !!! push code_sel2 push offset reset retf *) cli mov ds,data_sel mov ss,data_sel mov es,data_sel {---------------Восстановление атрибутов IDT----------------} {---------------для работы в реальном режиме----------------} {-------Возврат в реальный режим по команде MOV-------------} db 0fh,01h,1eh { LIDT idtr_r } dw idtr_r db 0fh,20h,0c0h { MOV EAX,CR0 } db 66h,25h { AND EAX,FFFFFFFEh } dd 0fffffffeh db 0fh,22h,0c0h { MOV CR0,EAX } push cs_real push ofs_ret retf {-----------------Работа в реальном режиме------------------} {---------------Восстановление регистров после--------------} {------------------возврата в реальный режим----------------} ret_r: xor ax,ax mov ds,ax mov ds,[4*60h] { DS, } mov ss,real_ss { SS, } mov es,real_es { ES } mov sp,real_sp { и SP } end; if res=0 then {-------Перепрограммирование контроллеров прерываний--------} {-------------для работы в реальном режиме------------------} pic(0) else {---------Размаскирование контроллеров прерываний-----------} {---------------после сброса микропроцессора----------------} begin port[$21]:=184; port[$a1]:=13; end; {---Разрешение маскируемых и немаскируемых прерываний---} en_int; {-----В случае возникновения исключения вывод его номера-----} gotoXY(1,20); {----------Анализ возврата МП из защищенного режима---------} if res=0 then s:='по команде MOV' else s:='через сброс МП'; writeln('Возврат из защищенного режима выполнен ',s); writeln('Скан-код нажатой клавиши - ',scan,' - ESC'); end. 5. Результати роботи програми Розроблена програма реалізує перехід у захищений режим і виводить на екран відомості про тип процесора і виводить вміст регістру флагів і іншу інформацію о системі. Потім реалізується цикл чекання переривання від клавіатури при натисканн клавіші ESC, під час цього обробляються переривання від таймеру і по кожному п’ятому тіку таймеру виконується змінення кольору бордюру. Після завершення циклу чекання натиску клавіші ESC програма реалізує виняткову ситуацію для виникнення 13 переривання, яке обробляється створеним перериванням, яке вилучає із стеку дескриптор помилки і обминає виняткову ситуацію. В кінц програма повертається у реальний режим і відновлює старі таблиці GDT та IDT. 6. Висновки В даній розрахунково-графічній роботі розроблено програму, що реалізує захищений режим роботи мікропроцесора, обробку апаратних і програмних переривань, засвоєно основні принципи роботи мікропроцесора у захищеному режимі при використанн сегментної моделі пам’яті, порядок обробки переривань, структуру таблиць GDT та IDT. |
|