Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm для Windows/Dos > клавиатура в дос


Автор: xach 21.12.2007, 03:13
у меня есть резидентная прога которая вешает свой обработчик на 9h - прерывание (от клавы то бишь) как мне перехватывать нажатия клавиш не поганя информацию для всех последующих обработчиков?
Код

in al,60h
;...
jmp far dword [addr]

этот вариант не катит (экспериментально убедился =) )

addr - адрес дефольтного обработчика...
если делать всё самому то бишь сбрасывать флаг прерывания:
Код

mov al,20h
out 20h,al

и не вызывать дефольтный обработчик, а ставить
Код

iret

тогда всё прекрасно работает...вотъ...
 smile 
З.Ы. всё под чистым досом!!!
З.З.Ы. возможно любое решение. не обязательно с прерыванием, можно и с какой-либо функций дос...лишь бы работало...

заранее мерси!

Автор: xach 21.12.2007, 09:33
вот начирикал!
прога в резиденте на escape выводит нолик в левой верхней части экрана. загвоздка в том, что в вин98 отлично пашет (реально клава свободна для ввода команд и т.д.), а под чистым досом подвешивает всё!

написана на фасме.

Код

org 100h

start:
    mov ax,3509h
    int 21h
    mov [addr],bx
    mov [addr+2],es
    mov dx,int9
    mov ah,25h
    int 21h

    mov dx,0ffh
    int 27h

int9:
    pusha
    pushf
    push es

    in al,60h
    dec al
    jnz .nocall
    push 0b800h
    pop es
    mov di,80*2
    mov [es:di],word 0b30h
.nocall:

    pop es
    popf
    popa
    jmp far dword [cs:addr]

addr:    dw 0


есть идеи?

Автор: ksili 21.12.2007, 09:42
Дык она точно резидентно загружается? по-моему нет. поэтому в винде она просто висит в памяти как один из процессов. А в ДОСе многозадачности нет, вот она одна и выполняется

Добавлено через 2 минуты и 36 секунд
Если приведённый код и есть вся программа, то в ней нету корректного завершения программы. Правда я на фасме не писал

Автор: xach 21.12.2007, 09:45
не-не-не!..она возвращает управление volcov commander-у а потом уже виснет...а в винде всё тоже верно, ибо окно-то консольное однозадачное!..хоть и эмуляция.

она и не должна завершаться...загрузочная часть заканчивается int 27h и dos оставляет прогу в резиденте, то бишь просто не даёт никому записаться по этому адресу. а всю работу делает обработчик прерывания...вотъ...

Автор: ksili 21.12.2007, 09:47
Как она может виснуть, если она уже вернула управление в DOS? Или систему вешает сам установленный обработчик при первом нажатии клавиши?

Автор: xach 21.12.2007, 09:49
да, как только жмёшь на клавишу - виснет...даже не выводит символ...а в консоли винды всё ок...

Автор: ksili 21.12.2007, 09:59
Цитата(xach @  21.12.2007,  13:33 Найти цитируемый пост)
jmp far dword [cs:addr]

а это что такое? Разве так надо возвращаться из обработчика прерывания?

Автор: dumb 21.12.2007, 10:04
Цитата(xach @  21.12.2007,  09:33 Найти цитируемый пост)
    mov dx,0ffh
    int 27h

у тебя только PSP занимает 100h + твой код. навскидку - сделай mov dx,200h.

а вообще, обычно делают так:
Код

org 100h
start: jmp init
; код обработчиков
init:
...
  mov dx, offset init
  int 27h

Автор: ksili 21.12.2007, 10:08
Вот здесь
Цитата(xach @  21.12.2007,  13:33 Найти цитируемый пост)
jmp far dword [cs:addr]

во время выполнения программы [cs:addr]конечно указывает на обработчик, но ведь потом же программа выгружается и cs может измениться. По-моему, адрес перехода в стандартный обработчик надо указывать по-другому

Автор: xach 21.12.2007, 10:17
ksili, dumb, спасибо всё заработало. я и вправду забыл про 100h начального смещения...пишешь его всё время, а потом уже и забываешь что это значит...

 smile 

[eof]

Автор: dumb 21.12.2007, 10:17
Цитата(ksili @  21.12.2007,  10:08 Найти цитируемый пост)
По-моему, адрес перехода в стандартный обработчик надо указывать по-другому 
нет, там все нормально: при установке обработчика в таблицу векторов прерываний записывается указатель на наш обработчик в форме seg:ofs, где seg = cs, т.е. при вызове обработчика cs устанавливается как нужно.

Автор: drwatson 27.4.2009, 23:50
у меня похожая задача: надо по нажатию ctrl+alt+p сделать так чтобы дос перестал реагировать на клаву и начал заново реагировать при повторном нажатие ctrl+alt+p. Само сабой программа резидентная. Вот только не пойму почему постоянно вылетает из доса с ошибкой:
 http://ipicture.ru/Gallery/Viewfull/18074817.html
Мой код:
Код

code    segment
        assume  cs:code,ds:code
        org     100h
start:  jmp     load
    old    dd  0
    status    db  1 ;0-off 1-on

key_h    proc
    pushf
    push ax
    push es
    push ds

    push    cs
    pop    ds

    in al,60h
    cmp al,25 ;p
    jne old_h
    xor ax,ax
    mov es,ax
    mov ah,es:[417h]
    test ah,4   ;ctrl
    jz old_h
    test ah,8   ;alt
    jz old_h

    inc status
    jmp exit

old_h:    test status,1
    jz exit
      pop ds
      pop es
      pop ax
      call      cs:old
      iret
exit:
    in    al,61h
    mov    ah,al
    or    al,80h
    out    61h,al
    xchg    ah,al
    out    61h,al

    mov    al,20h
    out    20h,al

    pop    ds
    pop    es
    pop    ax
    iret

key_h    endp
end_key_h:

load:    mov    ax,  3509h
    int     21h
    mov     word ptr old,  bx
    mov     word ptr old + 2,  es
    mov    ax,  2509h
    mov    dx,  offset key_h
    int    21h
    mov    ax,3100h
    mov    dx, (end_key_h-start + 10Fh) / 16
    int    21h
code    ends
        end     start

Автор: airyashov 28.4.2009, 08:03
Цитата(drwatson @ 27.4.2009,  23:50)

Код

key_h    proc
    pushf
    push ax
    push es
    push ds

  ....
exit:
    in    al,61h
    mov    ah,al
    or    al,80h
    out    61h,al
    xchg    ah,al
    out    61h,al

    mov    al,20h
    out    20h,al

    pop    ds
    pop    es
    pop    ax
    iret


одна из ошибок которую вижу
это флаги из стека убрать при выходе по метке exit

Автор: drwatson 30.4.2009, 21:24
Цитата(airyashov @  28.4.2009,  08:03 Найти цитируемый пост)
одна из ошибок которую вижу
это флаги из стека убрать при выходе по метке exit


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

Автор: drwatson 1.5.2009, 12:38
Ну раз тут так хорошо помогают, позволю себе задать еще один вопрос. А как теперь эту резидентную программу корректно выгрузить? И еще желательно освободить память. А то я просто восстанавливаю вектор девятого прерывания, но программа работает не стабильно.

Автор: Akina 1.5.2009, 22:44
Цитата(drwatson @  1.5.2009,  13:38 Найти цитируемый пост)
как теперь эту резидентную программу корректно выгрузить?

Резидентная программа перехватила обработчики некоторых прерываний и сохранила их старые адреса. Для выгрузки надо проверить, что текущие векторы прерываний указывают на резидент. Если это так - просто восстанавливаем старые адреса обработчиков. Если это не так - то сверху стоИт ещё один перехват, и надо принимать специальные меры, которые заключаются в оставлении после себя "заглушки", переадресующей напрямую на сохранённый адрес (far jmp ptr, 5 байт всего). После чего блоки памяти, занимаемые резидентом, освобождаются (в первом случае) либо урезаются (во втором) соотв. функцией 21 прерывания. Впрочем, во втором случае бывает, что на заглушки находится место в, например, блоке среды резидентной части (например, если резидент работал с файлами, блок среды при постановке наверняка не освобождался).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)