Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты в разделе

Коцюрбенко Алексей aka Жерар
Статус: Мастер-Эксперт
Рейтинг: 126
∙ повысить рейтинг »
Evgen aka Chuma
Статус: 5-й класс
Рейтинг: 18
∙ повысить рейтинг »
nikitos82.01
Статус: 1-й класс
Рейтинг: 0
∙ повысить рейтинг »

∙ Assembler

Номер выпуска: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!
пиши ли вот так


    start:
    push cs
    pop ds


или вот так


    mov [cs:pos_cursor],dx
    mov dx,[cs:pos_cursor]


удачи!

Консультировал: Евгений Иванов
Дата отправки: 28.12.2005, 13:20
Рейтинг ответа:

НЕ одобряю 0 одобряю!


Консультирует Ayl:

Здравствуйте, Macshm!

При запуске программы регистры не обнуляются, а имеют предопределенное значение. В частности, в регистр DX заносится адрес кодового сегмента.
В Приложении - установка регистров для COM-программы.
Поэтому тебе нужно не заносить неизвестно что в свою переменную, а инициализировать вначале регистр.

Приложение:

Консультировал: Ayl
Дата отправки: 28.12.2005, 13:37
Рейтинг ответа:

НЕ одобряю 0 одобряю!

Консультация # 20577:

Здравствуйте, помогите, пожалуйста, бедному студенту.
Нужна помощь в написании программы по перехвату прерываний клавиатуры.
В книжках ничего конкретного не почерпнул, копаться в рассылках не охото, нормальные статьи найти немогу, преподователь злой и не помогает - вот к Вам обращаюсь.
Суть программы в том, что при нажатии на клавишу должен происходить перехват этого прерывания, и подмена выходных параметров. В частности, если нажата буква \'a\' - на экране должна появиться буква \'b\' и наоборот.
Кое-что, конечно, препод подсказал - но все равно ничего не работает. Если раньше прога хоть вешала намертво комп, то сейчас вообще ничего не происходит.
Помогите, пожалуйста. Расскажите, где основная ошибка и что надо откорректировать. Заранее списибо!

Дата отправки: 08.05.2005, 15:48
Вопрос задал: raynor_y
Всего ответов: 3
Страница онлайн-консультации »


Консультирует Евгений Иванов:

Здравствуйте, raynor_y!
сохраняй регистры в прерывании!!!!
и не вызывай из своего обработчика то же самое прерывание.
смотри файл

Консультировал: Евгений Иванов
Дата отправки: 08.05.2005, 23:47
Рейтинг ответа:

НЕ одобряю 0 одобряю!


Консультирует 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 и их подмена. Вывод на экран также будет формироваться внешней программой.
От этого можешь отталкиваться.

Приложение:

Консультировал: Ayl
Дата отправки: 11.05.2005, 14:39
Рейтинг ответа:

НЕ одобряю 0 одобряю!


Консультирует Стас:

Здравствуйте, 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
Есть еще несколько вариантов решения той же проблемы.

Консультировал: Стас
Дата отправки: 13.05.2005, 00:17
Рейтинг ответа:

НЕ одобряю 0 одобряю!

Консультация # 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

Удачи
Если будут вопросы, можно спросить в минифоруме

Приложение:

Консультировал: Сурин Борис Павлович
Дата отправки: 17.08.2008, 22:39
Рейтинг ответа:

НЕ одобряю 0 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!


В избранное