Всем привет! Пишу ось, с целью познания мира Настроил контролёр прерываний на векторы 20h и 28h Сформировал IDT ,влепил все дескрипторы такими db 0h, 0h, 08h, 0h, 0h, 10001110b, 0h, 0h, настраиваю смещения обработчиков в них. И когда в коде настройки контролёра разрешено прерывание mov al, 11111101b ; OCW1 out 21h, al (пробую с клавиатурой или с таймером) то при старте перегружается комп Кто скажет в чём, где, какая ошибка, как сделать что бы работало? С шести вечера колупаюсь, комп раз 20 перегружался! %) Благодарю за внимание Код прикрепил.
0136 Ну, во-первых, есть ошибка в вычислении адреса GDT перед переключением в защищённый режим: Код (Text): xor eax, eax ; вычисляется физ. адрес GDT mov ax, seg_gdt ; (4000h) shl eax, 4 add ax, offset ds:Zero_descriptor ; прибавляется к физ.адрeсу смещение в сег. данных mov LA_GDT, eax ; сохр. физ. адреса GDT Физический адрес -- это 4 байта (реально до 20 бит), поэтому и используется регистр EAX. Но почему выполняем 16-разрядное сложение, а не 32-разрядное? Ну а во-вторых, что, собственно, и вызывает глюк: судя по коду в IDT, обработчики всех прерываний имеют точку входа 8:0, что соответствует нулевому физическому адресу памяти. Ну а Ваша программа явно на ходится не там. Более того, обработчиков прерываний в ней я вовсе не обнаружил (хотя в полвторого ночи внимательно смотреть откровенно не хочется).
; Реальный режим xor eax, eax ; EAX=0 mov ax, seg_gdt ; AX=сегмент таблицы shl eax, 4 ; EAX=физический адрес сегмента add ax, offset ds:Zero_descriptor ; +16разрядное смещение mov LA_GDT, eax ; сохр. физ. адреса GDT Выделен ведь отдельный сегмент под GDT, нулевой дескриптор стоит по адресу seg_gdt:0000. Можно вообще не добавлять смещение. Вот что с IDT: ; Это всё ещё реальный режим. xor eax, eax mov ax, seg_idt ; настроим IDT mov ds, ax shl eax, 4 ; вычислим физ. адрес IDT add ax, offset Gate_descriptor0 mov LA_IDT, eax ; сохранение полного физ. адреса IDT ; настройка смещений шлюзов xor eax, eax mov eax, seg_cs32 shr eax, 4 mov edx, eax add eax, offset int_0 mov word ptr ds:Gate_descriptor0, ax shr eax, 16 mov word ptr ds:Gate_descriptor0+6, ax SII, ошибка в чём то другом. Спасибо тебе
0136 От того, что смещение равно нулю, факт ошибки никуда не исчезает. Она лишь не приводит к неправильному результату, но не более того. Так что аккуратней будьте с адресной арифметикой. Тоже некорректное сложение. Вы думаете, что не может возникнуть переноса из 15-го разряда, который в таком случае будет потерян, и в результате в EAX получится неверный адрес? Возможно, в конкретном случае переноса действительно возникнуть не может, но такое сложение -- ошибочное. Грамотно написанная программа не "закладывается" на размещение своих кишок в памяти, за исключением совсем уж особых случаев (типа загрузчика, который грузится BIOSом в строго определённую область). Ну а дальнейший код вообще мутный какой-то...
Прошу извинения, нашёл ошибку, перепутал некоторые команды в процесе инициализации IDT. Просьба админу - закройте тему. Всем спасибо