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

Ваш аккаунт

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

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

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

tsr, обработчик прерывания

58K
06 мая 2010 года
bubatist
9 / / 04.05.2010
Привет всем. Мне надо сделать резиднетную программу, обработчик прерывания с клавиатуры. Собственно я его и сделал, однако столкнулся с такой проблемой - не могу вывести ни символ ни сообщение с помощью функций dos - под виндой просто ошибка вылазит: "процессор NTVDM обрануружил недопустимую инструкцию", думал дело в том что работаю с портами, загружался через dos - система просто висла. Через Bios получается выводить символы, но мне нужно через DOS, разобраться почему не работает.
Взгляните пожалуйста:
Цитата:

text segment 'code'
assume cs:text,ds:text
org 256
main proc

jmp init

old_handler dd 0

new_h proc;
push ax
push bx
push cx
push dx
push ds

catch:

in al,60h
mov bl,al
push ax
in al,61h
or al,80h
out 61h,al
pop ax

cmp bl, 10h


ja not_our_key
je key_pressed

key_pressed:

mov cx, 5
mov al, 41h
mov ah, 0ah
int 10h

mov al,20H
out 20H,al
out 0a0h, al

xor al, al
;mov dl, 01h - стоит мне раскоментировать, как программа выдает ошибку
;mov ah, 06h
;int 21h

jmp exit

not_our_key:
pop ds
pop dx
pop cx
pop bx
pop ax

mov al, 20h
out 20h, al
out 0a0h, al
jmp cs:old_handler
;jmp exit

exit:
pop ds
pop dx
pop cx
pop bx
pop ax

mov al, 20h
out 20h, al
out 0a0h, al
iret

init proc;
mov ax, 3509h
int 21h
mov word ptr old_handler, bx
mov word ptr old_handler+2, es

mov ax, 2509h
mov dx, offset new_h
int 21h

mov dx,offset init
int 27h

init endp
text ends
end main



И объясните пожалуйста для чего нужны эти строчки:
push ax
in al,61h
or al,80h
out 61h,al
pop ax
и зачем нужно завершать обработчик таким образом:
mov al, 20h
out 20h, al
out 0a0h, al

поскольку программирую я недавно, и это черновой вариант программы прошу ни судить строга))

1.8K
06 мая 2010 года
LM(AL/M)
332 / / 20.12.2005
in al,61h/or al,80h/out 61h,al -- сигнал об успешном получении кода клавиши
только по-моему нужно еще сбросить этот бит и снова послать

mov al, 20h/out 20h, al -- сигнал об окончании обработки прерывания (специфика контроллера клавиатуры, др. прерывания завершаются просто по iret)

а вот out 0a0h, al по-моему к клавиатуре не относится

насчёт того почему прога виснет пока ничего не скажу, может быть попозже (поразбираться надо)
58K
06 мая 2010 года
bubatist
9 / / 04.05.2010
буду очень признателен Вам. Я перелопатил много информации, и никак не могу понять почему int 21h вызывает ошибку
252
07 мая 2010 года
koderAlex
1.4K / / 07.09.2005
эмуляция dos-а в виндовсе не очень хорошая . лучше использовать виртулку с досом 6.22 .

некоторые функции доса нельзя использовать в обработчиках прерываний .
58K
07 мая 2010 года
bubatist
9 / / 04.05.2010
Цитата:
эмуляция dos-а в виндовсе не очень хорошая . лучше использовать виртулку с досом 6.22 .

некоторые функции доса нельзя использовать в обработчиках прерываний



своими глазами видел похожую программу, перехват нажатий клавиш и вывод их скан кодов, но она была не резидентная. и использовался там int 21h. к тому же я вроде добавил команды:
mov al,20H
out 20H,al
как я понял они разрешают прерывания.

1.8K
07 мая 2010 года
LM(AL/M)
332 / / 20.12.2005
вот что написано в techhelp-е по поводу вызова ф-ций ДОС из обработчиков прерываний:

When your program gets control via a timer interrupt INT 08H or INT 1cH or the keyboard interrupt INT 09H or any asynchronously-generated event, you must be very careful about using DOS functions.

The reason is that DOS is not reentrant. DOS might be processing a service call at the time of the interrupt. If you then issue another INT 21H, you risk disaster.

In general, when InDOS is set, you may use only DOS fns 01H-0cH (low-level character I/O). When it is clear, you can use all DOS fns...
58K
07 мая 2010 года
bubatist
9 / / 04.05.2010
Цитата:
In general, when InDOS is set, you may use only DOS fns 01H-0cH (low-level character I/O)

- так я как раз использую низкоуровненвый вывод. Вот я приведу пример программы, которую я нашел на этом форуме, ее написал некто Vov4ik. Она перехватывает прерывания и выводит их через int 21h, но она не резидентная:

Цитата:
ideal
model tiny
codeseg
org 100h
start:

mov ax,3509h
int 21h ; AL=vector to get ES:BX=return vector

mov [oldofs],bx
mov ax,es
mov [oldseg],ax
;-------------------------------------
mov ah,9
mov dx,offset mess
int 21h
;-------------------------------------
mov ax,2509h
mov dx,offset int9
int 21h ; AL=int num to set DS:DX=new handler
;---------- Настройка клавиатуры ---------------------------
mov al,0f3h
out 60h,al
call wait_kbd
mov al,01111111B ; Slower keyboard
out 60h,al
;-------------------------------------

jmp $ ; Main program ;-)

;--------------- Выход из программы ----------------------
exit:
; add sp,6
mov sp,0fffeh

mov dx,[oldofs] ;
mov ax,[oldseg] ;
mov ds,ax ;
mov ax,2509h ;
int 21h ; AL=int num to set DS:DX=new handler

mov al,20h
out 20h,al ; EOI
out 0a0h,al ; secondary
;-------------------------------------
mov al,0f3h
out 60h,al
call wait_kbd
mov al,0
out 60h,al ; Faster keyboard
ret
;-------------------------------------
int9:
in al,60h
mov bl,al

in al,61h
mov ah,al
or al,80h
out 61h,al

xchg ah,al
out 61h,al

mov al,bl
;-------------------------------------
cmp bl,0fah
je send_eoi ; ACK

test bl,80h ; something pressed
jz obrab

cmp bl,81h ; escape depressed
jne zero_cl

inc cl
cmp cl,3 ; Depressed
je exit
jmp obrab
zero_cl:
mov cl,0
obrab:
;-------------------------------------
push ax
shr al,4
call hex

pop ax
and al,0fh
call hex

mov dl,' '
call print
send_eoi:
mov al,20h
out 20h,al ; EOI signal
out 0a0h,al ; secondary
iret
;--------------- Вывод байта на экран ---------------------------------------
hex:
add al,'0'
cmp al,'9'
jbe nol
add al,'A'-'9'-1
nol:
mov dl,al
print:
mov ah,6
int 21h
ret
;------------------- Ожидание готовности клавиатуры ------------------
wait_kbd:
push cx
xor cx,cx
wk:
in al,64h
test al,10b
loopnz wk
pop cx
ret
;-------------------------------------
mess db 13,10,'Keyboard scancode viewer version 1.',13,10
db 'Copyright (c) 2006, ExTRA Laboratories [Vov4ik].',13,10
db 'Press ESCAPE three times to exit.',13,10,'$'
oldseg dw ?
oldofs dw ?
end start

1.8K
07 мая 2010 года
LM(AL/M)
332 / / 20.12.2005
Цитата: bubatist
- так я как раз использую низкоуровненвый вывод.


я это к тому написал что проблема не в вызове дос а вашем обработчике -- ищите зло в нём. Вы гоняли свою программу в отладчике? Смотрели что происходит при вызове ДОС и тд?
А по поводу примера -- если прога не резидентная то мы можем монопольно использовать в обработчике ф-ции ДОС -- так что никаких ограничений тут нет.

58K
07 мая 2010 года
bubatist
9 / / 04.05.2010
Цитата:
я это к тому написал что проблема не в вызове дос а вашем обработчике -- ищите зло в нём. Вы гоняли свою программу в отладчике? Смотрели что происходит при вызове ДОС и тд?



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

1.8K
07 мая 2010 года
LM(AL/M)
332 / / 20.12.2005
лучше всего наверн. TurboDebugger (см. http://docstore.mik.ua/bcpp/r78_5.htm#18), но можно и стандартный debug.com использовать (идёт в поставке МСДОС/Винды); я кстати в своей практике больше debug.com использовал
в обработчике посмотрите вот что: он валится на вызове дос-функции или после; ещё попробуйте сделать не-резидентную версию и посмотрите будет ли она так же падать. ещё у вас там кажется идёт вызов старого обработчика, помотрите всё ли нормально с этим вызовом
ещё в вашем коде я не увидел инструкций запрета/разрешения прерываний (cli/sti) обычно их вставляют в обработчики прерываний
можете ещё если хотите выслать исполняемый файл (мне самому ассемблировать невозможно, нет тасма), может немного покопаюсь в нём
58K
07 мая 2010 года
bubatist
9 / / 04.05.2010
Если будет настроение покопайтесь пожалуйста, прикрепляю файл. Сам поковыряюсь еще.
58K
11 мая 2010 года
bubatist
9 / / 04.05.2010
пишу сюда конечно больше на удачу, может кто то нибудь зайдет и объяснит мне в чем все же дело... я пропатчил свою прогу таймером, теперь она проверяет флаг критической ошибки и indos флаг, но что то работает как то странно. либо по нажатию "х" сразу ошибка, либо символ выведет и ошибка, в общем как то так.

Цитата:
.model tiny
.186
.code

org 100h
start:
jmp init

new_timer proc
pusha
pushf
push es
push ds

mov al, active_task
cmp al, 0ffh
jnz end3

les bx, InDOSFlag
mov al, es:[bx]
test al, es:[bx-1]
jz end3


execute:
mov dl, 23h
mov ah, 06h
int 21h

;mov ah, 0eh
;mov bh, 0ah
;mov al, 41h
;int 10h
;mov al, 0
mov active_task, al



end3:
pop ds
pop es
popf
popa
jmp cs:old_timer
new_timer endp








new_h proc
cli
pusha
pushf
push es
push ds
in al,60h
mov bl,al
push ax
in al,61h
or al,80h
out 61h,al
pop ax

cmp bl, 10h
jnz not_our_key
jne key_pressed


key_pressed:

mov active_task, 0ffh
jmp end1

not_our_key:
pop ds
pop es
popf
popa
jmp cs:old_handler
end1:
sti
mov al, 20h
out 20h, al
popf
popa

ret
new_h endp




init proc;
mov ax, 3509h
int 21h
mov word ptr old_handler, bx
mov word ptr old_handler+2, es

mov ax, 2509h
mov dx, offset new_h
int 21h

mov ax, 3508h
int 21h
mov word ptr old_timer, bx
mov word ptr old_timer+2, es

mov ax, 2508h
mov dx, offset new_timer
int 21h




mov ah, 34h
int 21h
mov word ptr InDOSFlag, bx
mov word ptr InDOSFlag+2, es



mov dx,offset init
int 27h

init endp
old_handler dd 0
InDOSFlag dd 0
active_task db 0
old_timer dd 0
end start

37K
18 мая 2010 года
airyashov
18 / / 09.06.2008
вы видимо считаете что переменные вам не нужны
 
Код:
mov dx,offset init
int 27h

init endp
old_handler dd 0
InDOSFlag dd 0
active_task db 0
old_timer dd 0
end start
58K
19 мая 2010 года
bubatist
9 / / 04.05.2010
не понял вас... может вы имели ввиду, что будучи объявленными за пределами собственно резидента они не могут быть им использованы?
58K
19 мая 2010 года
bubatist
9 / / 04.05.2010
то есть я должен в обработчик был добавить:
push ds
push cs
pop ds
правильно?
37K
19 мая 2010 года
airyashov
18 / / 09.06.2008
Цитата: bubatist
не понял вас... может вы имели ввиду, что будучи объявленными за пределами собственно резидента они не могут быть им использованы?


именно вы же оставляете резидент только до метки init

37K
19 мая 2010 года
airyashov
18 / / 09.06.2008
Цитата: bubatist
то есть я должен в обработчик был добавить:
push ds
push cs
pop ds
правильно?


если так используете переменную
mov active_task, 0ffh
то да

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