РАССЫЛКИ ПОРТАЛА RFPRO.RU Лучшие эксперты в разделе Номер выпуска: | 1645 | Дата выхода: | 23.06.2017, 17:15 | Администратор рассылки: | Лысков Игорь Витальевич (Старший модератор) | Подписчиков / экспертов: | 41 / 15 | Вопросов / ответов: | 3 / 6 | Консультация # 32331: доброе время суток, уважаемые эксперты! Помогите разобраться в проге (см. прил.). она должна прятать курсор,затем восстанавливать его, вместо этого курсор устанавливается где-то на середину окна... Смотрел в отладчике- в переменную pos_cursor загружается число 1500h, т.е. dx=1500h, откуда оно? (WinXP)... Консультация # 20577: Здравствуйте, помогите, пожалуйста, бедному студенту. Нужна помощь в написании программы по перехвату прерываний клавиатуры. В книжках ничего конкретного не почерпнул, копаться в рассылках не охото, нормальные статьи найти немогу, преподователь злой и не помогает - вот к Вам обращаюсь. Суть программы в том, что при нажатии на клавишу до... Консультация # 141621: Здравствуйте, Уважаемые!!! Помогите, ПОЖАЛУЙСТА, с вот такой вот задачкой: «Требуется найти среднее арифметическое 5-ти двухбайтовых чисел массива, хранимых в памяти в дополнительном коде, полученный результат преобразовать в символьную форму и вывести на монитор». Я пыталась что-то сделать, но пока не получается. Вот после запуска этой програм... Консультация # 32331: доброе время суток, уважаемые эксперты! Помогите разобраться в проге (см. прил.). она должна прятать курсор,затем восстанавливать его, вместо этого курсор устанавливается где-то на середину окна... Смотрел в отладчике- в переменную pos_cursor загружается число 1500h, т.е. dx=1500h, откуда оно? (WinXP) Дата отправки: 28.12.2005, 13:03 Вопрос задал: Macshm Всего ответов: 2 Страница онлайн-консультации » Консультирует Евгений Иванов: Здравствуйте, Macshm! пиши ли вот так или вот так mov [cs:pos_cursor],dx mov dx,[cs:pos_cursor]
удачи! Консультирует Ayl: Здравствуйте, Macshm! При запуске программы регистры не обнуляются, а имеют предопределенное значение. В частности, в регистр DX заносится адрес кодового сегмента. В Приложении - установка регистров для COM-программы. Поэтому тебе нужно не заносить неизвестно что в свою переменную, а инициализировать вначале регистр. Приложение:
Консультация # 20577: Здравствуйте, помогите, пожалуйста, бедному студенту. Нужна помощь в написании программы по перехвату прерываний клавиатуры. В книжках ничего конкретного не почерпнул, копаться в рассылках не охото, нормальные статьи найти немогу, преподователь злой и не помогает - вот к Вам обращаюсь. Суть программы в том, что при нажатии на клавишу должен происходить перехват этого прерывания, и подмена выходных параметров. В частности, если нажата буква \'a\' - на экране должна появиться буква \'b\' и наоборот. Кое-что, конечно, препод подсказал - но все равно ничего не работает. Если раньше прога хоть вешала намертво комп, то сейчас вообще ничего не происходит. Помогите, пожалуйста. Расскажите, где основная ошибка и что надо откорректировать. Заранее списибо! Дата отправки: 08.05.2005, 15:48 Вопрос задал: raynor_y Всего ответов: 3 Страница онлайн-консультации » Консультирует Евгений Иванов: Здравствуйте, raynor_y! сохраняй регистры в прерывании!!!! и не вызывай из своего обработчика то же самое прерывание. смотри файл Консультирует Ayl: Здравствуйте, raynor_y! Хм... Ошибок много. Во-первых, у тебя не резидентная программа! Вот трассировка действий твоей программы: 1. Установить сегмент данных - ок. 2. Получить адрес старого обработчика 16-го прерывания - ок. 3. Сохранить адрес в переменных - ок. 4. Установить свой обработчик - ок. Обсуждение написания обработчика - дальше. 5. Установить ds:bx на адрес старого обработчика. Хм. А зачем? Непонятное действие. 6. Комментированные строки. Записать по адресу ds:chr_out значение регистра al. А куда указывает ds? правильно - на сегмент старого обработчика. Интересно, я бы, пожалуй, тоже обиделся на такую запись. 7. Вывести на экран строку, завершающуюся символом \'$\' и начинающуюся с адреса ds:chr_out. Ну, сегментный регистр по-прежнему указывает на сегмент старого обработчика, а вот будет ли там символ доллара - я не уверен. Кстати, прога вылетает, скорее всего, еще на шаге 6. 8. Завершить программу с выходом в ДОС. Итак, что ты имеешь: 1. Неправильная установка регистра ds 2. После возможного завершения программы ты теряешь адрес старого обработчика и при запуске следующей программы вызов 16-го прерывания все равно приведет к ошибке 3. Программа не резидентная, т.к. не остается в памяти после завершения. Теперь по поводу обработчика. Допустим, что его вызвали. Что о делает. А делает он то, что в первой же строке обращается к самому себе! Рекурсия, причем безусловная! Т.е. зацикливание. Очень быстро произойдет переполнение стека - и опаньки! Неправильный алгоритм. И последнее. Насколько я понял из задания, тебе нужно отлавливать нажатия на клавиши и подменять \'a\' на \'b\', а \'b\' на \'a\'. но все дело в том, что 16-е прерывание - программное! И работает только при прямом обращении. Т.е. если программа не будет вызывать 16-е прерывание, то и работать это не будет. В то же время любое нажатие или отпускание клавиши генерирует на аппаратном уровне прерывание IRQ1, которое соответствует вектору 9. Т.е. любое нажатие клавиши вызывает обработчик 9-го прерывания! Может, с ним лучше поиграть? И еще два вопроса. Зачем ты при написании резидента создаешь EXE-программу? Да, это не ошибка, но написание резидента в виде EXE-модуля гораздо сложнее написания такого же резидента, но в виде COM-программы. Второй вопрос - ты используешь 32-разрядные регистры или команды 386-го процессора? Если нет - зачем использовать .386? Достаточно .286, хотя твой код вполне компилируем и на 8088. Это, как ты понимаешь, не ошибка, но если бы я был твоим преподом, то в первую очередь задал бы этот вопрос, чтобы выяснить, а понимаешь ли ты вообще эту директиву. В общем, см. в приложении резидент на 16-е прерывание в виде COM-программы. Он очень простой, практически не делает никаких действий, только устанавливает новый обработчик прерывания и завершается резидентно. Теперь при любом получении нажатия клавиши через 16-е прерывание будет осуществляться проверка на скен-коды клавиш A и B и их подмена. Вывод на экран также будет формироваться внешней программой. От этого можешь отталкиваться. Приложение:
Консультирует Стас: Здравствуйте, raynor_y! 1) накой тебе сдался PSP, Chr_out (который ты почему-то 9 функцией 21 прерывания пытаешься вывести)? 2) вызывая Int 16 из Int 16 ты намертво зацикливаешся. 3) mov ax,4C00h int 21h выгружает твою прогу из памяти ПОЛНОСТЬЮ, при этом Int16 yt восстанавливаешь. Тоже ерунда. 4) Вообще в данном случае перехват Int16 не лучший вариант, есть много других способов получить код нажатой клавиши минуя ah=0 int 16h. Тем не менее вот такой вариант: (COM файл) model tiny 386 code org 100h start: jmp begin ; ф-ция intproc: or ah,ah jnz loc1 pushf call dword ptr cs:oldint16 cmp ax,1e61h jnz loc2 mov ax,3062h loc2: iret loc1: jmp dword ptr cs:oldint16 oldint16: _off dw ? _seg dw ? ; ф-ция закончена begin: mov ax,3516h int 21h mov ax,es mov _seg,ax ;Запомнить старый Int16 mov _off,bx mov ax,cs mov ds,ax lea dx,intproc mov ax,2516h int 21h ;Установить новый lea dx,begin ;Оставить резидентом!!! int 27h end start А вот более приемлимый вариант перехватывающий INT9: model tiny 386 code org 100h start: jmp begin ; ф-ция intproc: pushf call dword ptr cs:oldint9 ;пусть отработает оригинальный и положит в буфер клавиатуры код push ds push bx push ax push 40h pop ds mov bx,ds:[1ch] ;какой последний код был положен в буффер cmp bx,1eh jnz loc1 add bx,20h; буффер круговой loc1: sub bx,2 mov ax,[bx] cmp ax,1e61h ;только маленькая \'a\' !!!! большая будет:1e41 (c ctrl-a =1e01h) и т.д. jnz loc2 mov ax,3062h ;большая 3042h mov [bx],ax ;вот собственно и подмена loc2: pop ax pop bx pop ds iret oldint9: _off dw ? _seg dw ? ; ф-ция закончена begin: mov ax,3509h int 21h mov ax,es mov _seg,ax ;Запомнить старый Int09 mov _off,bx mov ax,cs mov ds,ax lea dx,intproc mov ax,2509h int 21h ;Установить новый lea dx,begin ;Оставить резидентом!!! int 27h end start Есть еще несколько вариантов решения той же проблемы. Консультация # 141621: Здравствуйте, Уважаемые!!! Помогите, ПОЖАЛУЙСТА, с вот такой вот задачкой: «Требуется найти среднее арифметическое 5-ти двухбайтовых чисел массива, хранимых в памяти в дополнительном коде, полученный результат преобразовать в символьную форму и вывести на монитор». Я пыталась что-то сделать, но пока не получается. Вот после запуска этой программы появляется надпись « переполнение деления».
Дата отправки: 17.08.2008, 17:51 Вопрос задал: Alena De Lon Всего ответов: 1 Страница онлайн-консультации » Консультирует Сурин Борис Павлович: Здравствуйте, Alena De Lon! Привет. Вы наделали кучу ошибок, от того и переполнение :) В приложении исправленный код программы. Там, где существенные ошибки, я поставил два восклицательных знака Чтобы проще их отлавливать, первые свои программы запускайте в пошаговом режиме в отладчике Теперь подробнее. 1) Основная ошибка: Вы заказали модель памяти TINY, а завершаете, как EXE, через 21 прерывание (СОМ - через 20-е) У Вас присутствует сегмент стека и данных, поэтому COM-файл получить не могли, только EXE. Это противоречие и привело к ошибке
2) Перед началом первого цикла Summ: add ax,[bx] ; Прибавляем к ax содержимое bx inc bx inc bx ;!! 2 байта нужно Loop Summ необходимо было инициализировать регистр CX - следовательно, Ваш цикл мог выполняться сколько раз? Далее, каждое число занимает в памяти 2 байта, а чему равно dlina dw $-mas ? М ожете проверить - 10! Но Вы это число не используете НО!! Нужно увеличивать BX на 2, а не на 1 - отмечено жирным выше
3) Вы не учли, что сумма может быть (а в Вашем примере, будет) отрицательной. Знак нужно обрабатывать отдельно. Я сделал это с помощью дополнительной переменной Sign
4) Определяя среднее, Вы поделили на BH. В этом случае частное будет в AL, в AH - остаток. Это не было учтено при последующем делении на 10
Удачи Если будут вопросы, можно спросить в минифоруме
Приложение:
Оценить выпуск | Задать вопрос экспертам главная страница | стать участником | получить консультацию техническая поддержка Дорогой читатель! Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно! МЫ РАБОТАЕМ ДЛЯ ВАС! |
Комментариев нет:
Отправить комментарий