Доброй ночи всем =) тут возник вопрос, который ну никак не получается уложить в голове... (либо начитался и все перепуталось либо вообще не понимаю) вот если в RM аппаратные прерывания отображались на фиксированные вектора прерываний, то вот в PM, значит мы должны (например чтобы написать свой обработчик прерывания, уж если откровенно то перехватить просто аппаратное прерывание =)) придется самому перенаправлять эти самые аппаратные прерывания на, ну так сказать, произвольные вектора??? ( и при этом надо отключать APIC??)
Как бы покорочи тебе ответить чтобы не забивать голову всякой всяченой. Если у нас PIC то ему поступает прерывание на вектор IRQ . PIC передает сообщение процессору о прерывание и сообщает номер вектора прерывания. Номер вектора соответствует вектору перрывания из таблицы прерываний. Для RM это адресса отсчитываются от 0, вернее там IDTR содержит базу ноль и лимит 0FFFFh. Для PM это вектор из таблице IDT. Зачем? В IDT часть векторов в PM используютя под исключения. Их больше чем в RM, так что нам надо подвинуть аппоратные прерывание. Это делается путем перепрограммирования PIC перед переходом в защищенный режим. При программировании сразу двигается 8 векторов для слейв и 8 для мастера.
нет, не понимаю.. =( сказать честно, совет перепрограммировать PIC для меня звучит крайне устрашающе ... ведь в RM при получении прерывания на шине формировался адрес который получался из суммы номера IRQ и базового значения ( = 8) Так вот это я не могу смириться с тем что настолько все изменено в PM или все же есть возможность получить номер аппаратного прерывания подобным путем??
Vic PM все тоже самое только адресс IDT задается произвольный и формат дескриптора(английское слово читаем перевод) другой. Просто для PM мы меняем базового значения, чтобы не было канфликтов между исключениями и аппортаными прерываниями которых сатало больше. А так все тоже самое. Только PIC генерирует не настоящий адресс(к режиму работы процессора это не имеет отношение), а псевдо адресс .Который соответствует вектору прерывания, который уже и выбирается из таблице прерываний. И вообще отпровляет он это по шине данных.
слушай, если не сложно можешь попробовать объяснить... про IDT вроде понятно все, про то что номера векторов аппаратных прерываний такие же как в RM использовать нельзя так как будет конфликт тоже ясно. Но вопрос вот в чем, все таки как (не говорю программно, - сам хочу все таки пробовать) но теоретически что нужно сначала сделать что потом , вот есть адрес IDT , а дальше то как?? понимаю что возможно, напрягаю с таким количеством вопросов, но хочется разобраться, если что кинь что нить почитать ...
Vic Вот есть адресс IDT формат известный. Вектора аппоратных прерываний известны так как сами их перепрограммировали. Остается написать обработчик прерывания и повесить его на нужный вектор. Запрещаем прерывания Устанавливаем вектор прерывания путем записи в таблицу IDT дескриптора прерывания разрешаем прерывания. Дескриптор прерывания. Возьмем Interrupt Gate 4 слова слово первое - 15-0 адресс смещениее функции обработчика прерывания слово второе - селектор сегмента. Сегмент кода с нужным кольцом слово третье - атрибуты слово четвертое - 32-16 оставшаяся часть адреса смещениее функции обработчика прерывания В обработчике прерывания пишем код. .... Посылаем код конца прерывание EOL. IRET // возврат из прерывания
спасибо, тут почти все понятно, дело в том что вопрос как раз и стоит в том что : Вот, например, в RM прерывание от клавиатуры int 9h, и его можно было перехватить в таблице векторов прерываний. Но как мне в PM, скажем перехватить тот же IRQ1 ? Говоря конкретнее, НА КАКОЙ ВЕКТОР вешать обработчик?? И еще вопросик, разве не нужно использовать IRETD вместо IRET?
Смотря куда ты подвинешь IRQ вектора перед переходом в PM при программировании контроллера. В реальном режиме база была 8 (вектор = IRQ + 8), в защищенном тебе надо подвинуть, допустим, на 0x20. Тогда 0x20 будет IRQ0, 0x21 - IRQ1 и т.д. Опкод 0xCF в реальном режиме означает IRETW, а в защищенном IRETD. Если явно дописать префикс 0x66, то будет наоборот PS. Вот код для перенаправления IRQ, вроде рабочий.. Код (Text): redirect_IRQ: ; BX = { BL = Начало для IRQ 0..7, BH = начало для IRQ 8..15 } ; DX = Маска прерываний IRQ ( DL - для IRQ 0..7, DH - IRQ 8..15 ) ; APIC Off mov ecx, APIC_BASE_MSR rdmsr or eax, 1000b wrmsr mov al,11h out 0a0h,al out 20h,al mov al,bh out 0a1h,al mov al,bl out 21h,al mov al,02 out 0a1h,al mov al,04 out 21h,al mov al,01 out 0a1h,al out 21h,al mov al,dh out 0a1h,al mov al,dl out 21h,al ; APIC On rdmsr and eax, not 1000b wrmsr ret mov dx, 0FFFFh mov bx, 2820h call redirect_IRQ
Great Поправочка: не в реальном и защищённом, а в 16- и 32-разрядном Если в защищённом режиме работа идёт в 16-разрядном сегменте кода, когда это будет тот же самый "IRETW". Другое дело, что 16-разрядный защищённый режим распространения не получил, но помнить про разрядность кода всё же надо. Ведь есть ещё и 64-разрядный режим. Vic Опять-таки это неточно. Прерывание от клавиатуры -- это IRQ1. И отображено оно может много куда (вместе с другими прерываниями). А INT 9 -- это программный вектор, на который отображено аппаратное прерывание IRQ 1 в процессе инициализации компутера средствами BIOS. Программист волен это отображение изменить, перепрограммировав контроллер прерываний.
Vic А это зависит от того, на какой вектор оно было повешено при инициализации защищённого режима. Каждая ось вправе это делать по-своему. Более того, вектор, вообще говоря, может быть разным при каждой новой загрузке системы, хотя на практике такое вряд ли имеет место.
Кстати, вопрос. Есть разные версии винды. Как определить номер записи в IDT для произвольного аппаратного прерывания? Гугл дал - контроллировать версии HAL и хранить хардкодед таблички. Есть вариант красивее? И что с программными прерываниями, будет ли single step вешаться на 1й дескриптор? Правка: для аппаратных нашел HalGetInterruptVector(), но он obsolete.
Вот статью нашел новерно поможет. http://www.codeproject.com/KB/system/GetInterruptVectorInfo.aspx Там дваа варианта. Первый через I/O APIC. А второй HalGetInterruptVector
Joes Назначение программных прерываний с векторами до 20h включительно жёстко зашито самой архитектурой процессора -- см. интеловские мануалы.
я тут прочел, что в системах Windows назначаются базовые вектора: ведущему контроллеру - 50h, а ведомому - 58h. так вот , значит ли это что номер прерывания в IDT, например в WinXP , будет равен #IRQ + 50h (либо 58h) ?? (хотя кажется догадываюсь что это конечно вовсе не так)
Vic Будет. Но только в том случае, если Винда действительно использует древний PIC, а не современный APIC
понятно честно говоря конечно и не надеялся, что это окажется выходом из ситуации =)) p.s. А вот вопрос, абсолютно не по теме, но уж очень распирает =) парни, откуда вы столько знаете все =) ? я вот в универе, хотя профиль совсем другой у меня... так голову ломаю постоянно как только появляется очередная проблема с реализацией программы, приходиться перелопатить кучу ссылок и лит-ры, при чем процентов 98 - мусор всякий... понимаю, что вопросы такие не задают на подобного рода форумах, но если есть желание можете поведать, посто интересно =)
Vic Кто как Но думаю, что в 99% -- самообразование в широком смысле слова. В вузе мало что получишь. Зацикленность на Си++, модных технологиях и т.д. мало что даёт для понимания низкоуровневых вещей.