Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

DOS, перехват прырвания 09h и ввод с клавиатуры во время обработки - фантастика?

62K
30 мая 2013 года
LWhisper
33 / / 27.11.2012
Всем привет!

В вузе поставили задачу - написать резидента, который ловит нажатие клавиш, по Ctrl+X выгружается, по Ctrl+S просит ввести имя диска и выводит информацию о нём.

С этой и аналогичными (с вводом) задачами у всего потока возникли проблемы. Я свою работу сдал, но живёт оно на честном слове и вешает систему на раз два.
Поясню ситуацию, объясню - как её вижу я, и хочу услышать авторитетное мнение - прав ли я?

Ситуация:
Идеальный обработчик прерывания:

 
Код:
cli
pushf
; Наш код
call _originalHandler
sti
iret
Но! Нам то нужен ещё и ввод, поэтому мы, как умные Маши, делаем так:

 
Код:
pushf
call _originalHandler

; Ждём ввода
mov ah, 01h
    int 21h
; Наш код
iret
И примерно с вероятностью 50% прога виснит после обработчика.

Как я это вижу:
Ядро вызывает обработчик прерывания. Сохраняет адрес возврата, флаги.
Мы вызвали оригинальный обработчик. Управление системе через iret не вернули.
Но её было достаточно того, что выполнился оригинальный обработчик, и она готова к новому вводу.

Вызывается новый обработчик (н.п. наш ввод, или мы просто отпустили Ctrl+S).
Он заменяет флаги и адрес возврата. Выполняется. Допустим, это было не Ctrl+S/X, мы просто вызвали оригинальный обраточик и вернули управление системе. Всё отлично.

Заканчивает работу наш первый обработчик. Ищет куда бы ему вернуться, и возвращается в какое-то совершенно незнакомое место, так как другой обработчик уже заменил его адрес вызова своим, выполнился и вернулся.

Результат не предсказуем.

Как надо было сделать:
Разбиваваем обработчик на несколько стадий.

Стадия 1:
Cli. Ловим Ctrl+S/Ctrl+X. Обрабатываем Ctrl+X. При Ctrl+S переключаемся на стадию 2 и завершаем обработчик. Sti.

Стадия 2:
Cli. Ctrl+S/Ctrl+X не обрабатываются. Весь ввод, воспинимается, как ввод имени диска (для простоты - один пришедьший скан-код). Выводим информацию о диске. Переключаемся на стадию 1. Завершаем обработчик. Sti.

И никаких int21h(01h). Оригинальный обработчик вызывается в конце, а не в начале.


Верно ли моё видение ситуации?
Является ли последнее верным и\или единственно верным вариантом?

(Ввод с мыши, COM-порта и др. устройств не рассматривается).

P.S. Извините за некоторый сумбур, последнее решение пришло в голову в процессе написания поста, а изначально он выглядел, как: что за хрень, это задание вообще не выполнимо. :D
62K
30 мая 2013 года
LWhisper
33 / / 27.11.2012
Не, это не интересно. В Windows всё разруливается корректно самой осью. В реальном режиме никто не работает. Личное виртуальное пространство. Опять же - кнопка одна. :)

В общем, проблема решена. Действительно помогли отказ от чтения и системным вызовом и печати строки через него же.
Обоим отписавшимся спасибо.
414
30 мая 2013 года
CassandraDied
763 / / 24.05.2012
А где popf? Если не перепутал, то cli не позволяет обрабатывать аппаратные прерывания, а прерывание INT — не оппаратное, так что новый обработчик никак не может быть вызван, пока не будет выполнена sti.
 
Код:
mov ah, 01h
    int 21h
А мы такую штуку делали через мониторинг буффера клавиатуры. И прерывания были не нужны.
Цитата:
И примерно с вероятностью 50% прога виснит после обработчика.


А в отладчик посмотреть?

62K
30 мая 2013 года
LWhisper
33 / / 27.11.2012
popf не нужен. pushf делается для iret, так как как один раз флаги восстановит оригинальный обработчик, а второй - наш.

Там ещё должно быть сохранение и восстановление регистров - но это уже лирика.

cli запрещает повторный вызов прерывания, до вызова sti. В том то и беда, что мы не трогаем этот флаг, так как ожидаем ввода с клавиатуры в процессе обработки прерывания клавиатуры (даже звучит, как верх кретинизма :D). И решение я вижу только одно - изложенное выше.

У нас задача именно написание резидентной программы, которая подменяет обработчик прерывания, оставляет кусок себя в памяти, а сама завершается. С обычной консолкой и проблем бы не было. Ну, а для мониторинга чего либо, нужно предыдущее состояние и текущее. А у нас прерывание дёргается на каждое отжатие\нажатие кнопки.

А в отладчике, как я и писал, такая ситуация:

 
Код:
Вызов обработчика 1 - возврат в хххх:yyyy

Вызов обработчика 2 - возврат в xxxx:zzzz
Завершение обработчика 2 - возвращаемся в xxxx:zzzz

Завершение обработчика 1 - возвращаемся хрен знает куда и, можем повесить систему
414
30 мая 2013 года
CassandraDied
763 / / 24.05.2012
Тут много вариантов, как можно реализовать эту плюшку. Например, не использовать прерывания, а читать из портов, что тебе не удастся проверить только в DOS. Но, мне кажется, у тебя просто код кривой, потому что УМВР. Почитай чьи-нибудь книги, что ли.
И, да, с popf — это я ошибся, он не нужен.
252
30 мая 2013 года
koderAlex
1.4K / / 07.09.2005
вы делаете системный вызов внутри обработчика прерывания . ясен пень зависнет .
вам нужно полностью подменить обработчик прерывания своим .
алгоритм обработчика прост как два пальца :
1.считать скан-код с клавы .
2.отфильтровать нужное вам.
3.отфильтровать не нужное никому .
4.преобразовать скан-код в аски-код и поместить в буфер .
end

если бы у вас не было требования на Ctrl+X и Ctrl+S , то можно было бы упростить .
252
30 мая 2013 года
koderAlex
1.4K / / 07.09.2005
и ещё . прерывания в досе работают в режиме с приоритетами .
и выше прерывания клавы только прерывания таймера .
cli и sti не нужны .
62K
30 мая 2013 года
LWhisper
33 / / 27.11.2012
Цитата: CassandraDied
Тут много вариантов, как можно реализовать эту плюшку. Например, не использовать прерывания, а читать из портов, что тебе не удастся проверить только в DOS. Но, мне кажется, у тебя просто код кривой, потому что УМВР. Почитай чьи-нибудь книги, что ли.


Тобишь, ожидание ввода символа, заменить на

 
Код:
loop:
  in al, 60h
  test al, al
jz loop
? Если это будет работать - шикарно.
УТВР в такой же ситуации с вводи через системный вызов? :D
Читать книжки по данной проблеме не хочется, так как никто больше мне не даст работать в реальном режиме, и эти знания представляются мне чистой воды теорией.

Цитата:
вы делаете системный вызов внутри обработчика прерывания . ясен пень зависнет .
вам нужно полностью подменить обработчик прерывания своим .
алгоритм обработчика прост как два пальца :
1.считать скан-код с клавы .
2.отфильтровать нужное вам.
3.отфильтровать не нужное никому .
4.преобразовать скан-код в аски-код и поместить в буфер .
end

если бы у вас не было требования на Ctrl+X и Ctrl+S , то можно было бы упростить .

и ещё . прерывания в досе работают в режиме с приоритетами .
и выше прерывания клавы только прерывания таймера .
cli и sti не нужны



Проблем с Ctrl+X / Ctrl+S я не вижу. Резидент в любом случае нужен. А на что его вешать - какая разница? Проблема пока именно с вводом.

Что же касается подмены своим: а это как? Откуда же я знаю - что из этого не нужно никому? В какой буфер помещать? Наконец, до меня могло быть уже зарегистрировано с десяток резидентов и они вызывают друг-друга цепочкой (н.п. я работаю в нортоне, у него есть хоткеи, как я понимаю - он подменяет прерывания своими, и я обязан вызывать его, иначе у меня нортон повиснит).

Тоесть на мой взгляд, проблема именно в том, что обработчик дёргается повторно до того, как закончил работать первый и адрес возврата из обработчика становится не валидным. Возможно, я ошибаюсь. Возможно, мы говорим об одном и том же разными словами.

414
30 мая 2013 года
CassandraDied
763 / / 24.05.2012
Цитата:
Тобишь, ожидание ввода символа, заменить на


А я точно не помню, что там за код должен быть. Открой Питера Абеля и почитай, ёпт. Я вчера у него нашёл код с портами в разделе о резедентных программах.
УМВР, когда нужно было написать резедентную программу, которая выводит текст на консоль и по нажатию кнопки меняет его цвет. Кнопка была одна, может, в этом дело. Но, увы, исходников не сохранилось. Проблемы были только с некоторыми кнопками, которые не хотели отлавливаться в командной строке Windows, какой-нибудь эмулятор DOS отработал бы нормально.
И почитай о буффере клавиатуры же.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог