$F6,$F7 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$27,$37 : cur_ofs:=cur_ofs+1;
$2F,$3F : cur_ofs:=cur_ofs+1;
$69 : cur_ofs:=cur_ofs+4;
$6B : cur_ofs:=cur_ofs+3;
$D4,$D5 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$98,$99 : cur_ofs:=cur_ofs+1;
$D0..$D3 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$C0,$C1 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+2;
$20..$23 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$24 : cur_ofs:=cur_ofs+2;
$25 : cur_ofs:=cur_ofs+3;
$84,$85 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$F6 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+2;
$F7 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+3;
$A8 : cur_ofs:=cur_ofs+2;
$A9 : cur_ofs:=cur_ofs+3;
$08..$0B : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$0C : cur_ofs:=cur_ofs+2;
$0D : cur_ofs:=cur_ofs+3;
$30..$33 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$34 : cur_ofs:=cur_ofs+2;
$35 : cur_ofs:=cur_ofs+3;
$A4,$A5 : cur_ofs:=cur_ofs+1;
$A6,$A7 : cur_ofs:=cur_ofs+1;
$AE,$AF : cur_ofs:=cur_ofs+1;
$AC,$AD : cur_ofs:=cur_ofs+1;
$AA,$AB : cur_ofs:=cur_ofs+1;
$6C..$6F : cur_ofs:=cur_ofs+1;
$F2,$F3 : cur_ofs:=cur_ofs+2;
$E8 : cur_ofs:=cur_ofs+3;
$9A : cur_ofs:=cur_ofs+5;
$EB : cur_ofs:=cur_ofs+2;
$E9 : cur_ofs:=cur_ofs+3;
$EA : cur_ofs:=cur_ofs+5;
$C3 : cur_ofs:=cur_ofs+1;
$C2 : cur_ofs:=cur_ofs+3;
$CB : cur_ofs:=cur_ofs+1;
$CA : cur_ofs:=cur_ofs+3;
$70..$7F : cur_ofs:=cur_ofs+2;
$E0..$E3 : cur_ofs:=cur_ofs+2;
$C8 : cur_ofs:=cur_ofs+4;
$C9 : cur_ofs:=cur_ofs+1;
$CD : cur_ofs:=cur_ofs+2;
$CC : cur_ofs:=cur_ofs+1;
$CE : cur_ofs:=cur_ofs+1;
$CF : cur_ofs:=cur_ofs+1;
$62 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$F8..$FD : cur_ofs:=cur_ofs+1;
$F4,$F5 : cur_ofs:=cur_ofs+1;
$9B : cur_ofs:=cur_ofs+1;
$65,$F0 : cur_ofs:=cur_ofs+1;
$0F : cur_ofs:=cur_ofs+2;
$D8..$DF : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
$26,$2E,
$36,$3E : cur_ofs:=cur_ofs+1;
$0F : cur_ofs:=cur_ofs+Dlin_Kom(cod2)+2;
$63 : cur_ofs:=cur_ofs+Dlin_Kom(cod1)+1;
end;
write(i:4,'. ',sel,':',cur_ofs1,' Код => ',hex(cod):3,';');
if (cur_ofs-cur_ofs1) >1 then write(' ',hex(cod1):3,' ');
if (cur_ofs-cur_ofs1) >2 then write(' ',hex(cod2):3,' ');
if (cur_ofs-cur_ofs1) >3 then write(' ',hex(cod3):3,' ');
if (cur_ofs-cur_ofs1) >4 then write(' ',hex(cod4):3,' ');
inc(i);
if cod=$9a then begin
writeln('Межсегментный переход!');
with table[i_table] do begin segm:=sel;ofs:=cur_ofs1;cod:=$9a;descr:=sel_descr; end;
inc(i_table); { Формирование дескриптора сегмента кода: }
init_gdt(i_descr,$ffff,lin_adr(cod_sel,0),acc_code,0,0);
inc(i_descr);sel_descr:=sel_descr+8;post(cod_ofs,cod_sel);
end;
until (cod=$C3) or (cod=$CB) or (cod=$C2) or (cod=$CA);{ret}
writeln('End of procedure');readkey;
end;{post}
begin
textbackground(0);clrscr;textcolor(15);
asm cli end; w:=0; i_table:=0;
for i:=0 to 9 do table[i].segm:=0;
memL[0:3*4]:=Longint(@int3); asm sti end;
i_descr:=6; sel_descr:=$30;Save_RG;
writeln('Значение DS,SS,ES,CS для реального режима : ', hex(Real_Znach_ds), ',',hex(Real_Znach_ss),',', hex(Real_Znach_es),' ',hex(Real_Znach_cs)); sel_cs:=Cseg;
asm mov ofs_analiz,offset analiz end; post(ofs_analiz,Cseg);
analiz;
writeln('w=',w,' sp=',sp_,' cod_=',hex(cod_),' bp=',bp_,' ss=',hex(ss_),' cs=',hex(cs_),' ds=',hex(ds_),' bx=',bx_); i:=0;
while table[i].segm<>0 do with table[i] do begin
writeln('segm=',segm, ' ofs=',ofs,' cod=',hex(cod),' desr=',hex(descr));inc(i);
end; readkey;
lim1:=0; lim2:=10;
{---Определение значения сегмента кода cs1 процедур,описанных в модуле PROT----}
cs1:=Seg(int_30h);
excep:=$ff; { Отличное от FFh значение переменной excep }
semaf:=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,0);
init_gdt(1,$ffff,lin_adr(cseg,0),acc_code,0,0);
init_gdt(2,$ffff,lin_adr(cs1,0),acc_code,0,0);
init_gdt(3,$ffff,lin_adr(dseg,0),acc_data+$60,0,0);
init_gdt(4,0,lin_adr(sseg,0),acc_stack,0,0);
init_gdt(5,4000-1,lin_adr($b800,0),acc_data,0,0);
{------Формирование данных регистра GDTR и его загрузка-----}
out_GDT; readkey; exit; init_gdtr;
{----Определение селектора (sel_ret) и смещения (ofs_ret)---}
sel_ret:=Cseg;
asm mov ofs_ret,offset ret_r end;
{-------------Формирование данных для перехода на метку ret_r после сброса МП-------}
save_ret_real(sel_ret,ofs_ret,5);
not_int;{------Запрет маскируемых и немаскируемых прерываний--------}
{--------------Формирование таблицы IDT-------------------- }
init_idt(0,ofs(exc_00),code_sel2,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_sel,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_11),code_sel2,acc_trap);
init_idt(12,ofs(exc_12),code_sel2,acc_trap);
init_idt(13,ofs(exc_13),code_sel2,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(PIC_1),code_sel2,acc_int);
init_idt($21,ofs(keyb),code_sel2,acc_int+$60);
for i:=2 to 7 do
init_idt($20+i,ofs(PIC_1),code_sel2,acc_int);
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_idtr_p;
init_idtr_r;
pic(1);
save_sreg;
real_sp:=SPtr;
if cpu_type=2 then
{--------Переход в защищенный режим для МП 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
db 0eah { Межсегментный переход на метку @prot }
dw offset @prot { для очистки буфера команд МП }
dw code_sel { и загрузки регистра CS }
@prot:mov ds,data_sel { DS, }
mov ss,stack_sel { SS }
mov es,video_sel { и ES }
mov ah,1 { Установка маркера: }
mov bx,1001h { строка 1, столбец 10 }
int 30h
mov ah,4 { Вывод строки s на экран: }
mov dh,1eh { видеоатрибут, }
mov si,offset s { адрес строки }
int $30
mov ah,1 { Установка маркера }
mov bx,004h
int 30h
mov ah,4 { Вывод строки s1 на экран: }
mov dh,30h
mov si,offset s1
int $30
mov ah,1 { Установка маркера }
mov bx,006h
int 30h
sti
@wait:
cmp semaf,0
jz @wait
cmp cpu_type,2
jnz @mov
db 9ah { межсегментный вызов процедуры reset }
dw offset reset
dw code_sel2
{---Подготовка к возврату в реальный режим по команде MOV---}
@mov:mov ds,data_sel
mov ss,data_sel
mov es,data_sel
{---------------Восстановление атрибутов IDT----------------}
db 0fh,01h,1eh { LIDT idtr_r }
dw idtr_r
{-------Возврат в реальный режим по команде MOV-------------}
db 0fh,20h,0c0h { MOV EAX,CR0 }
db 66h,25h { AND EAX,FFFFFFFEh }
dd 0fffffffeh
db 0fh,22h,0c0h { MOV CR0,EAX }
mov bx,offset ofs_ret
db 0ffh { Косвенный межсегментный переход на метку ret_r }
db 2fh { для очистки буфера команд МП и загрузки CS }
{db 2eh} {вместо 2fh}
{dw ofs_ret}
{-----------------Работа в реальном режиме------------------}
ret_r: xor ax,ax
mov ds,ax
mov ds,ds:[4*$60] { DS, }
mov ss,real_ss { SS, }
mov es,real_es { ES }
mov sp,real_sp { и SP }
end;
if res=0 then test_wr; { Если запрет сохранился - }
{ вырабатывается прерывание 13, обработчик которого }
{ с помощью процедуры reset сбрасывает МП }
{----------Размаскирование контроллеров прерываний----------}
port[$21]:=0; { первого КП }
port[$a1]:=0; { и второго КП }
{-----Разрешение маскируемых и немаскируемых прерываний-----}
en_int;
{-------------Проверка возникновения исключений-------------}
if excep<>$ff then {if excep=11 then
writeln('Обработано исключение 11 (селектор ', err shr 3,')')
else} writeln('Исключение ',excep);
{----------Анализ возврата МП из защищенного режима---------}
if res=0 then s:='по команде MOV' else s:='через сброс МП';
writeln('Возврат из защищенного режима выполнен ',s);
writeln('prov=',prov,ss);
readkey;
end.