Задание:
14. Написать обработчик прерывания 40d, который в защищенном режиме выводит содержимое дескриптора GDT на экран. Селектор дескриптора передается в регистре CX.
Общая схема решения задачи:
Добавить в таблицу прерываний прерывание 40d. Написать обработчик этого прерывания. В нём необходимо по числу, хранящемуся в CX найти место в таблице GDT, с которой начинается нужный дескриптор. Это можно сделать прибавив к адресу GDT размер дескриптора GDT умноженное на CX. Затем вывести на экран содержимое дескриптора.
Текст программы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
;Программа транслируется в COM - файл: ; TASM demo.asm ; Tlink demo.obj /t ; Demo.asm .386p ; Разрешение трансляции ; всех инструкций 80386 Gdt_Descriptor STRUC ; Шаблон дескpиптоpа GDT Seg_Limit dw 0 ; Длина сегмента Base_Lo_Word dw 0 ; Младшие 16 бит базового ; адреса Base_Hi_Byte db 0 ; Биты 16..23 базового адреса Acces_Rights db 0 ; Байт прав доступа Base_Top_Byte dw 0 ; Биты 24..31 базового адреса Gdt_Descriptor ENDS Idt_Descriptor STRUC ; Шаблон дескриптора IDT Int_Offset dw 0 ; Точка входа в процедуру ; обработки прерывания Int_Selector dw 0 ; Селектор сегмента в GDT db 0 ; Access db 0 ; Права доступа dw 0 ; Idt_Descriptor ENDS Code_Seg_Access Equ 10011011b ; Байт прав доступа деск- ; риптора сегмента кода Data_Seg_Access Equ 10010011b ; Байт прав доступа деск- ; риптора сегмента данных Disable_Bit20 Equ 11011101b ; Код команды 8042 для за- ; крывания линии A20 Enable_Bit20 Equ 11011111b ; Код команды 8042 для от- ; крывания линии A20 Port_A Equ 060h ; Порт A 8042 Status_port Equ 064h ; Порт состояния 8042 Cmos_Port Equ 070h ; Адрес порта CMOS-памяти ; Макро для записи базового адреса сегмента в дескриптор FILLDESCR MACRO Seg_Addr,Offset_Addr,Descr xor edx,edx ; EDX := 0 xor ecx,ecx ; ECX := 0 mov dx,Seg_Addr ; Сегментная часть mov cx,offset Offset_Addr ; Смещение call Form_32Bit_Address ; CX:DX := линейный ; адрес mov &Descr.Base_Lo_Word,dx ; Занесение базового mov &Descr.Base_Hi_Byte,cl ; адреса в дескрип- mov &Descr.Base_Top_Byte,cx ; тор ENDM CSEG SEGMENT Para USE16 public 'code' ASSUME cs:Cseg,ds:Cseg ORG 100h Start: jmp Main ; Глобальная дескрипторная таблица GDT EVEN Gdt label word ;********** Дескриптор, описывающий саму таблицу GDT ********** Gdt_Desc EQU $-gdt ; Селектор дескриптора Gdt1 Gdt_Descriptor <gdt_leng,,,data_seg_access,> ;****** Дескриптор, описывающий сегмент Cseg как кодовый ****** Cs_Code EQU $-gdt ; Селектор дескриптора Gdt2 Gdt_Descriptor<cseg_leng,,,code_seg_access,> ;** Дескриптор, описывающий Cseg как сегмент данных с пределом* ;** 0FFFEh. Он будет использоваться также в роли стекового. *** Cs_Data EQU $-gdt ; Селектор дескриптора Gdt3 Gdt_Descriptor<cseg_leng,,,data_seg_access,> ;************* Дескриптор, описывающий таблицу IDT ************* Idt_Pointer Gdt_Descriptor<idt_leng-1,,,data_seg_access> ;** Дескриптор, описывающий таблицу IDT реального режима ******* Idt_Real Gdt_Descriptor<3FFh,,,data_seg_access> ;********* Дескриптор, описывающий сегмент видеопамяти ********* Video_Desc EQU $-gdt ; Селектор дескриптора GdtB800 Gdt_Descriptor<1000h,8000h,0bh,data_seg_access> Gdt_Leng EQU $-gdt ; Длина таблицы GDT ;Таблица дескрипторов прерываний IDT. EVEN Idt label word ex0 Idt_Descriptor<offset ex0_proc,cs_code,0,10000111b,0> ex1 Idt_Descriptor<offset ex1_proc,cs_code,0,10000111b,0> ex2 Idt_Descriptor<offset ex2_proc,cs_code,0,10000110b,0> ex3 Idt_Descriptor<offset ex3_proc,cs_code,0,10000111b,0> ex4 Idt_Descriptor<offset ex4_proc,cs_code,0,10000111b,0> ex5 Idt_Descriptor<offset ex5_proc,cs_code,0,10000111b,0> ex6 Idt_Descriptor<offset ex6_proc,cs_code,0,10000111b,0> ex7 Idt_Descriptor<offset ex7_proc,cs_code,0,10000111b,0> ex8 Idt_Descriptor<offset ex8_proc,cs_code,0,10000111b,0> ex9 Idt_Descriptor<offset ex9_proc,cs_code,0,10000111b,0> ex10 Idt_Descriptor<offset ex10_proc,cs_code,0,10000111b,0> ex11 Idt_Descriptor<offset ex11_proc,cs_code,0,10000111b,0> ex12 Idt_Descriptor<offset ex12_proc,cs_code,0,10000111b,0> ex13 Idt_Descriptor<offset ex13_proc,cs_code,0,10000111b,0> ex14 Idt_Descriptor<offset ex14_proc,cs_code,0,10000111b,0> ex15 Idt_Descriptor<offset ex15_proc,cs_code,0,10000111b,0> ex16 Idt_Descriptor<offset ex16_proc,cs_code,0,10000111b,0> Idt_Descriptor 22 dup(<>) Int39 Idt_Descriptor<offset int10_proc,cs_code,0,10000110b,0> Int40d Idt_Descriptor<offset Int40_proc, cs_code,0,10000110b,0> Idt_Leng EQU $-Idt ; Длина таблицы IDT Mess db 'Protected Mode$' Len dw 14d Gate_Failure db "Error open A20$" Main: FillDescr cs,Gdt,Gdt1 ; Формирование 32-разряд- ; ного адреса из CS:GDT и ; запись его в дескриптор ; с номером Gdt_Desc. FillDescr cs,0,gdt2 ; Дескриптор Cs_Code ука- ; зывает на CSEG как на ; кодовый сегмент. FillDescr cs,0,gdt3 ; Дескриптор Cs_Data ука- ; зывает на CSEG как на ; сегмент данных. FillDescr cs,Idt,Idt_Pointer ; Дескриптор Idt_Pointer ; указывает на IDT. cli ; Запрет прерываний mov al,8fh ; Запрет немаскируемых out cmos_port,al ; прерываний jmp short $+2 mov al,5 out cmos_port+1,al mov ah,Enable_Bit20 ; Открываем адрес- call Gate_A20 ; ную линию A20 or al,al ; Если произошла jz A20_Opened ; ошибка, то mov dx,offset Gate_Failure ; выдать сообщение mov ah,9 ; на экран, разре- int 21h ; шить прерывания и sti ; вернуться в DOS int 20h A20_Opened: lea di,Real_CS ; Сохранение сегмента mov word ptr cs:[di],cs ; кода для перехода ; в реальный режим lgdt Gdt1 ; Загрузка GDTR lidt Idt_Pointer ; Загрузка IDTR mov eax,cr0 ; Переходим в защищенный or eax,1 ; режим, устанавливая mov cr0,eax ; бит 0 в регистре CR0 db 0EAh ; Дальний переход dw offset Protect ; с непосредственным dw Cs_Code ; операндом ; Работа в защищенном режиме. Protect: mov ax,Cs_Data mov ss,ax ; Регистры DS, ES и SS mov ds,ax ; содержат селектор mov es,ax ; сегмента Cs_Data call My_Proc ; Вызов рабочей процедуры cli mov eax,cr0 ; Переходим в реальный and eax,0FFFEh ; режим, сбрасывая бит 0 mov cr0,eax ; регистра CR0 db 0EAh ; Дальний переход с dw offset Real ; непосредственным Real_CS dw ? ; операндом ; Работа в реальном режиме. Real: lidt Idt_Real ; Загружаем регистр IDTR ; для работы в реальном ; режиме mov dx,cs ; Восстанавливаем mov ds,dx ; сегментные mov ss,dx ; регистры mov ah,Disable_Bit20 ; Закрытие адресной call Gate_A20 ; линии A20 sti ; Разрешение прерываний int 20h ; Выход в DOS ex0_proc: iret ; Обработчики особых ex1_proc: iret ; ситуаций ex2_proc: iret ; Здесь установлены ex3_proc: iret ; заглушки вместо ex4_proc: iret ; обработчиков ex5_proc: iret ex6_proc: iret ex7_proc: iret ex8_proc: iret ex9_proc: iret ex10_proc: iret ex11_proc: iret ex12_proc: iret ex13_proc: iret ex14_proc: iret ex15_proc: iret ex16_proc: iret ;************************************************************** ;Управление прохождением сигнала A20 ;ВХОД: (AH)=0DDH установить A20 всегда равным нулю ; (AH)=0DFh открыть адресный разряд A20 ;ВЫХОД: (AL)=0 8042 принял команду ; (AH)=2 сбой ;************************************************************** Gate_A20 PROC cli ; Запрет прерываний call Empty_8042 jnz Gate_1 mov al,0d1h ; Выдаем команду 8042 для out Status_Port,al ; записи в выходной порт call Empty_8042 jnz Gate_1 mov al,ah ; Записываем в порт A 8042 out Port_A,al ; код команды call Empty_8042 Gate_1: ret Gate_A20 ENDP ;************************************************************** ;Ждать пока буфер 8042 не опустеет ;Вход: нет ;Выход:(AL)=0 буфер пуст ; (AL)=2 не пуст ;************************************************************** Empty_8042 PROC push cx xor cx,cx ; CX = 0 (256 повторений) Empty_1: in al,Status_Port ; Порт 8042 and al,00000010b ; Бит 2 очищен ? loopnz Empty_1 pop cx ret Empty_8042 ENDP ;************************************************************** ; Формирование 32-разрядного адреса ; Вход : CX:DX - адрес в формате <сегмент:смещение> ; Выход: CX:DX - 32-разрядный линейный адрес Form_32Bit_Address PROC shl edx,4 add edx,ecx mov ecx,edx shr ecx,16 ret Form_32Bit_Address ENDP ;************************************************************** ; Процедура вывода строки на экран, работает в качестве ; обработчика прерывания. ; Вход : DS:BX - адрес сообщения ; DL - строка экрана ; DH - колонка экрана ;************************************************************** Int10_Proc Proc Near ; Обработчик прерывания pusha ; INT 39d xor cx,cx ; Очистка CX mov cl,dh ; CL = колонка sal cl,1 ; CL = CL*2 xor dh,dh ; DX = строка imul dx,160d ; Умножаем на число байт в строке add dx,cx ; Прибавляем смещение в строке ; Результат: DX = смещение в ; видеопамяти push Video_Desc pop es ; ES = сегмент видеопамяти mov di,dx ; DI = смещение в этом сегменте m: mov ax,[bx] ; AL = очередной символ строки cmp al,'$' ; Конец строки ? jz Ex ; Да - выход mov cx,es:[di] ; Получить атрибут в CH mov ah,ch ; AX = символ с атрибутом stosw ; Записать символ в видеопамять inc bx ; Перейти к следующему символу jmp short m ex: popa iret ; Возврат из прерывания Int10_Proc Endp Print Proc Near ; Вывод строки на экрна в защищённом режиме pusha ; xor cx,cx ; Очистка CX mov cl,dh ; CL = колонка sal cl,1 ; CL = CL*2 xor dh,dh ; DX = строка imul dx,160d ; Умножаем на число байт в строке add dx,cx ; Прибавляем смещение в строке ; Результат: DX = смещение в ; видеопамяти push Video_Desc pop es ; ES = сегмент видеопамяти mov di,dx ; DI = смещение в этом сегменте m10: mov ax,[bx] ; AL = очередной символ строки cmp al,'$' ; Конец строки ? jz _Ex ; Да - выход mov cx,es:[di] ; Получить атрибут в CH mov ah,ch ; AX = символ с атрибутом stosw ; Записать символ в видеопамять inc bx ; Перейти к следующему символу jmp short m10 _ex: popa ret ; Возврат из прерывания Print Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;Процедура перевода переменной типа word в строку ;;Входные параметры: ;;ax - байт ;;di - смещение выходной строки WordToStr proc pusha; add di,2; call ByteToStr; shr ax,8; sub di,2; call ByteToStr; add di,4; popa; ret; WordToStr endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;Процедура перевода 1 байта в строку ;;Входные параметры: ;;al - байт ;;di - смещение выходной строки ByteToStr proc pusha jmp end_ByteToStr_data Symbols db "0123456789ABCDEFGH"; end_ByteToStr_data: xor ah,ah; push ax; shr al,4; mov si,offset Symbols; add si,ax; mov bl,[si]; mov [di],bl; inc di; pop ax; and al,00001111b; mov si,offset Symbols; add si,ax; mov bl,[si]; mov [di],bl; popa ret; ByteToStr endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;Устанавливает si на смещение дескриптора сегмента, селектор ;;которого в CX GetGDT proc ;;Проверка селектора на действительность ;lar ax, cx; ;jz successful_loading; ;;Сюда попадаем в случае, когда селектор недействительный ; mov si,0; ; ret; ;successful_loading: mov si,offset gdt; mov bx,[si];загрузка длины таблицы mov ax,8; mul cx; mov cx,ax; add cx,8; cmp cx,bx; jb successful_cx; xor si,si; ret; successful_cx: add si,cx; ;cmp cx,bx; ; jng successful_cx ; popa ; xor si,si; ; ret; ;successful_cx: ; ;sub si,8; ; inc cx; ;m_loop: ; add si,8; ; loop m_loop ret; GetGDT endp ;************************************************************** ;Процедура обработка прерывания 40d ;В соответствии с заданием выводит на экран содержимое ;дескриптора GDT. ;Селектор дескриптора передаётся в регистре CX ;************************************************************** int40_proc proc near pusha jmp end_int40_proc_data Selector dw 0; str1 db " $"; Descriptorstr db "DESCRIPTOR GDT: $" Seg_Limitstr db "Seg Limit: $" Base_Addressstr db "Base Address: $" Access_Rightsstr db "Acces Rights: $" end_int40_proc_data: push es push Video_Desc ; В регистр ES заносим се- pop es ; лектор сегмента видеопа- ; мяти mov dh,0fh ; Очищаем экран call Paint_Screen mov Selector, cx; call GetGDT; or si,si; jnz no_error; ;;//Сюда попадём в случае неверного селектора jmp exit_int40d; no_error: ;;//начало вывода на экран дескриптора GDT mov ax,Cs_Data mov ds,ax ; DS - сегмент данных ; lea bx,Descriptorstr ; Адрес сообщения ; mov dx,0101h ; Координаты вывода ; call Print ; Вывод строки на экран ; mov si,offset idt_real ; mov ax,Cs_Data; ; mov ds,ax; ; DS - сегмент данных; ; lea bx,Seg_Limitstr ; Адрес сообщения ; mov dx,0101h ; Координаты вывода ; call Print ; Вывод строки на экран mov cx,8 mov di,offset str1; ;;Вывод длины сегмента mov dx,0101h; mov bx, offset Seg_Limitstr; call Print; mov dx,0F01h; ;lsl ax,Selector; первый способ mov ax,[si]; второй способ call WordToSTr; mov bx,offset str1; call print; ;;Вывод прав доступа mov dx,0102h; mov bx,offset Access_Rightsstr; call Print; mov dx,0f02h; ;Можно было сделать с помощью такой команды lar ax,Selector mov al,[si+5]; второй способ call ByteToStr; add di,2; mov al,'$'; mov [di],al; sub di,2; mov bx,offset str1; call Print; mov ax,[si+4] ;;Вывод базового адреса mov dx,0103h; mov bx,offset Base_Addressstr; call Print; ;;вывод старших бит 24-41 mov ax,[si+6]; call WordToStr; mov dx,0F03h; mov bx,offset str1; call Print; ;;вывод бит 16-23 mov al,[si+4] call ByteToStr; add di,2; mov al,'$'; mov [di],al; sub di,2; mov dx,1303h; call Print; ;;вывод младших 16 бит mov ax,[si+2] call WordToStr; mov dx,1603h; call Print; ;Это отключено. Оно выводило дескриптор целиком (цифры) на экран ;m_loopdesc: ; mov ax,[si]; ; call ByteToStr; ; inc si; ; add di,2; ; loop m_loopdesc; ; ; mov ax,Cs_Data ; mov ds,ax ; DS - сегмент данных ; lea bx,str1 ; Адрес сообщения ; mov dx,1001h ; Координаты вывода ; call Print ; Вывод строки на экран exit_int40d: pop es popa iret int40_proc endp; ;************************************************************** ;Процедура выполняющая какие-либо действия в защищенном режиме ;************************************************************** MY_PROC PROC pusha ; push es ; push Video_Desc ; В регистр ES заносим се- ; pop es ; лектор сегмента видеопа- ; ; мяти ; mov dh,0fh ; Очищаем экран ; call Paint_Screen ; mov ax,Cs_Data ; mov ds,ax ; DS - сегмент данных ; lea bx,Mess ; Адрес сообщения ; mov dx,200Bh ; Координаты вывода ; int 39d ; Вывод строки на экран ; pop es mov cx,4; int 40d; popa ret MY_PROC ENDP ;************************************************************** ; Процедура очищает экран и устанавливает цвета в соответствии ; с заданным атрибутом. ; Вход : ES - селектор дескриптора текстового видеобуфера ; DH - атрибут. ;************************************************************** PAINT_SCREEN PROC push cx si di es mov cx,80*25 ; Размер видеопамяти (слов) xor si,si ; SI и DI установим на xor di,di ; начало видеопамяти Paint1: lodsw ; Увеличиваем смещение в ; видеопамяти mov ah,dh ; Байт атрибута символа mov al,20h ; Код символа "ПРОБЕЛ" stosw ; Записываем символ с ат- ; рибутом в видеопамять loop Paint1 ; Повторить для каждого ; символа на экране pop es di si cx RET PAINT_SCREEN ENDP Cseg_Leng Equ $ ; Длина сегмента Cseg Cseg Ends End Start |
Результат работы программы:
№ опыта | CX | Результат |
1 | 1 | Seg Limit: 0579h;
AccessRights: 93h; Base Address: 000000 1280h; |
2 | 2 | Seg Limit: 0147h;
AccessRights: 93h; Base Address: 000000 13B4h; |
3 | 3 | Seg Limit: 03ffh;
AccessRights: 93h; Base Address: 000000 0000h; |
Вывод:
Был изучен защищённый режим микропроцессоров.