int09h_handler proc far
pusha
push es
push ds
mov ax,@data
mov ds,ax
push seg ab
pop ds
mov ax,0B800h
mov es,ax
mov es:ab,1F20h
inc ab
inc ab
in al,61h
mov ah,al
or al,80h
out 61h,al
mov al,ah
out 61h,al
mov al,20h
out 20h,al
pop ds
pop es
popa
iret
ab dw 0
int09h_handler endp
Вопрос о прерываниях
Обясните пожалуйста, для чего в аппаратных прерываниях произоводить настройку DS на CS. Речь идет о DOSе.
Если обработчик использует свою память через регистр DS (по умолчанию) то этот регистр нужно переназначать. Иначе как он обратится к своей памяти (можно еще и через другие регистры)?
Можно еще обращаться к памяти так:
cs: mov [local_var],ax
но это добавляет по одному байту префикса к каждой инструкции доступа к памяти.
Я надеюсь цель переназначения ясна?
И почему именно в аппаратных? Эта инфа и программных прерываний касается.
Переназначение именно на CS только в том случае если сегмент данных и кода совпадают (образно конечно, т.к. может это вообще бинарник без сегментов)
Ниже приведен код обработчика прерывания клавиатуры. При каждом нажатии клавиши он должен постепенно закрашивать экран синим цветом. Никак не могу разобраться почему он отказывается работать(программа зваисает). Укажите пожалуйста ошибку.
Хорошо бы посмотреть всю программу, как она ставит и снимает обработчик и чем занимается во время своей работы. Или обработчик выполняется всегда (TSR) ?
Код:
mov ax,@data
mov ds,ax
push seg ab
pop ds
mov ds,ax
push seg ab
pop ds
я вообще не понимаю..
Почему не
Код:
push cs
pop ds
pop ds
?
Кроме того наверное лучше так:
Код:
mov bx,ab ; mov bx,[ab]
mov [es:bx],1F20h ; es mov [bx],1F20h
mov [es:bx],1F20h ; es mov [bx],1F20h
Обработчик что-то успевает выводить?
Не наверное лучше так, а именно так. Ассемблер - не высокоуровневый язык - никто вместо аффтара не будет загружать смещение в регистр для дальнейшего обращения к памяти по этому смещению.
Думаю, если у автора ехешник, то push cs ; pop ds не пройдёт, т.к. сегменты кода и данных скорее всего разные, судя по части исходника.
В этом исходнике переменная находится прямо за кодом, т.е. в секции кода. А вообще все равно где она если так подумать. Вероятность ошибки при переписывании кода вместо нашей переменной очень мала ))
Да код вообще весьма странный... Аффтар явно только учится программировать на ассемблере. Например, непонятно, зачем дважды подряд инициализировать регистр ds, причем совершенно разными способами. А разговор о секциях здесь неуместен, потому что код явно расчитан на RM. Думаю, будет проще написать подобный код с нуля, чем разбирать имеющийся.
Цитата: Phantom-84
Да код вообще весьма странный... Аффтар явно только учится программировать на ассемблере. Например, непонятно, зачем дважды подряд инициализировать регистр ds, причем совершенно разными способами. А разговор о секциях здесь неуместен, потому что код явно расчитан на RM. Думаю, будет проще написать подобный код с нуля, чем разбирать имеющийся.
Если автор учится то это уже хорошо. А под секциями я нечаянно имел ввиду сегменты ))
Цитата: disasm
В этом исходнике переменная находится прямо за кодом, т.е. в секции кода.
А вот слона и не заметил... Прошу прощения.
Советую автору писать ком-файлы, сразу отпадут проблемы с сегментами.
А кто запрещает в exe-файле хранить код и данные вместе в одном сегменте?
Код:
int09h proc far
pusha
push es
push ds
in al,60h ;если нажата клавиша Esc
cmp al,1 ;- не выполнять
je bad_key ;наш обработчик
;...
in al,61h ;установка бита 7
push ax ;порта 61h
or al,80h
out 61h,al
pop ax
out 61h,al
mov al,20h ;команда контроллеру
out 20h,al ;прерываний
pop ds
pop es
popa
iret ;возврат в программу
bad_key: pop ds
pop es
popa
jmp old_int09h;вызво старого обработчика
int09h endp
pusha
push es
push ds
in al,60h ;если нажата клавиша Esc
cmp al,1 ;- не выполнять
je bad_key ;наш обработчик
;...
in al,61h ;установка бита 7
push ax ;порта 61h
or al,80h
out 61h,al
pop ax
out 61h,al
mov al,20h ;команда контроллеру
out 20h,al ;прерываний
pop ds
pop es
popa
iret ;возврат в программу
bad_key: pop ds
pop es
popa
jmp old_int09h;вызво старого обработчика
int09h endp
Так ли это? Что в приведенном коде нужно убрать, а что наоброт добавить?
1. jmp old_int09h
можно подробней расписать? Если это адрес старого обработчика то его явно те так надо вызывать. Можно через push,push,retf
2. in al,60h
А старый обработчик может быть тоже захочет отсюда прочитать?
Я бы посоветовал заменить полностью старый обработчик и не передавать ему управление в новом. А перед выходом из программы поставить всё на свои места.
Мой обработчик прерывания клавиатуры работает несколько иначе..
Код:
in al,0x60
; .... обрабатываем клавишу ....
in al,0x61
or al,1
out 0x61,al
; сброс PIC
mov al,0x20
out 0x20,al
; .... обрабатываем клавишу ....
in al,0x61
or al,1
out 0x61,al
; сброс PIC
mov al,0x20
out 0x20,al
Ах, да, совсем забыл. От клавиатуры идет минимум по 2 прерывания от каждой кнопки:
..нажата
[..нажата еще много раз, в случае если пользователь зажал кнопку]
..отпущена
disasm, а зачем использовать порт 0x61? Это же вроде устаревший подход или я ошибаюсь?
Новых подходов я пока не видел. Главное что этот - рабочий. Возможно есть и другие варианты..
Цитата:
jmp old_int09h
можно подробней расписать? Если это адрес старого обработчика то его явно те так надо вызывать. Можно через push,push,retf
можно подробней расписать? Если это адрес старого обработчика то его явно те так надо вызывать. Можно через push,push,retf
old_int09h - переменная в 4 байта. В первых двух записано смещений и в двух последних сегментная часть.
И еще, если ты (Disasm) предлагаешь вообще не передавать управления старому обработчику, то нужно ли в этом случае заносить код клавиши в буфер клавы и делать еще что-нибудь в этом роде?
Eternal Man, если ты перехватываешь прерывание в нерезидентной программе, то скорее всего можно ограничиться полностью самостоятельной обработкой нажатия клавиш. В "буфер клавы" нужно заносить коды клавиш, если ты планируешь читать их оттуда посредством стандартных функций BIOS, но в этом случае тебе и транслировать их придется по правилам BIOS. На мой взгляд, раз уж ты решил перехватывать обращение к клавиатурному обработчику, лучше организовать и свой клавиатурный буфер, и использовать свои правила трансляции сканкодов нажатых клавиш, такие, какие устраивают тебя, а не BIOS.
Возможно я не прав, но кажется можно обратно сканкод через порты в контроллер клавиатуры запихнуть. В этом случае можно будет передать управление старому обработчику и все будет ок
Если написание своего обработчика преследует цель отлова нажатий клавишь Shift, Alt и Ctrl, советую почитать TechHelp! или HelpPC, раздел по области памяти BIOS. Все нужные флаги там содержатся, что позволяет значительно упростить самописный обработчик, вызывая его после оригинального. Также посмотри справку по расширенным скан-кодам.
Vov4ick, сканкод может быть повторно прочитан, но есть вероятность, что это уже будет другой сканкод, т.к. после первого прочтения KBC может обновить свой выходной буфер.