Клавиатура (через порты)

Тема в разделе "WASM.OS.DEVEL", создана пользователем clotho, 17 июн 2010.

  1. baldr

    baldr New Member

    Публикаций:
    0
    Регистрация:
    29 апр 2010
    Сообщения:
    327
    Либо дёрнется само, либо ой. Прошивки 8042, они коварные. :derisive:
     
  2. clotho

    clotho New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2010
    Сообщения:
    21
    В моём случае был <<Ой>>, точнее даже <<йОп>> =((( попробую в цикле писать много, авось дёрнется.

    Хотя хотелось бы более чёткие указания...
     
  3. clotho

    clotho New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2010
    Сообщения:
    21
    Запись в цикле приводит к перезагрузке, попробую запретить прерывания.
     
  4. clotho

    clotho New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2010
    Сообщения:
    21
    Аналогично.

    Может я что не так делаю? Может надо на сях через inb и outb? Может, для начала, сделать это с прявязкой к ОС? Я иссяк =( Но ведь пишут же как-то люди...
     
  5. clotho

    clotho New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2010
    Сообщения:
    21
    Кстати, вроде бы, нажатие-то есть, тока символ не вводится...
     
  6. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    Код приведи, что ли :)
    А то ведь непонятно куда и как и что.
     
  7. clotho

    clotho New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2010
    Сообщения:
    21
    Я код использую приведённый выше, ну если вы настаиваете
    Код (Text):
    1. _asm
    2. {
    3.     push dx
    4.     push ax
    5.     // E Down
    6.     mov al, 0d2h
    7.     out 64h, al
    8.     mov dl, 30h
    9.     mov al, dl
    10.     out 60h, al
    11.     //E Up
    12.     mov al, 0d2h
    13.     out 64h, al
    14.     mov dl, 30h
    15.     add dl, 80h
    16.     mov al, dl
    17.     out 60h, al
    18.     pop ax
    19.     pop dx
    20. }
    Эксперименты провожу на WinPXsp2 (соответственно вызываю код из нулевого кольца).
    Выход в нулевое кольцо взял в гугле, его тоже надо приводить?

    P.S. Как только задача будет решена для XP меня заставят её делать для *NIX, вот по этому очень хочется порты, хотя может вы посоветуете что-то другое.
     
  8. clotho

    clotho New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2010
    Сообщения:
    21
    Только там уже не буква <<E>>
     
  9. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    Было упоминание С, кроме того было интересно именно оформление вызова.
    Нет, но его работоспособность/глюки тоже могут влиять.

    Теперь по сути кода. Самое главное - не вижу ожиданий готовности 8042. Вы ему пихаете в глотку до того, как он что-то успевает прожевать. Это не Xeon, а гораздо более медленная железяка. Именно поэтому
    я настаивал. В том коде, кстати, задержки были хотя бы упомянуты ("ждать").
    Код (Text):
    1.     mov dl, 30h
    2.     mov al, dl
    3.     out 60h, al
    Зачем через dl?
    Код (Text):
    1.     push dx
    2.     push ax
    3.     ...
    4.     pop ax
    5.     pop dx
    Это все как компилируется? Как 32 бита? Тогда почему сохраняем только 16 бит? Нет, работать будет в любом случае. Просто непонятно.
     
  10. clotho

    clotho New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2010
    Сообщения:
    21
    Vic3Dexe, полностью с Вами согласен, код странный, просто не мой. Я уже перепробовал по всякому, и ждать готовности только перед посылкой 0D2h и перед каждой операцией с портом, результат всегда одинаковый. Режим 32 бита, собираю из консоли <<cl>>. Вечером приведу код выхода в нулевое кольцо и вариант с задержками.

    Спасибо что всë ещë это читаете.
     
  11. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    Без обид, но частично дело в этом. Копипаст до добра не доводит :)

    Код не странный, он вполне себе, но недописаный явно.
    Еще, нужны не просто задержки (особенно умиляют задержки циклом времен 8086), а ожидание готовности (IBF, OBF):
    Код (Text):
    1. ReadyR:
    2.     in   al,64h
    3.     test al,1
    4.     jz   ReadyR
    5.     ;можно читать из 0060h (OBF=1, в выходном буфере 8042 есть данные)
    Код (Text):
    1. ReadyW:
    2.     in   al,64h
    3.     test al,2
    4.     jnz  ReadyW
    5.     ;можно писать в 0060h (IBF=0, входной буфер 8042 свободен)
    Ессно, если что-то пойдет не так, тут мы и повесимся, поэтому нуно прикрутить какой-нить таймаут.
    Не надо, в нем все равно никто не будет разбираться, речь вообще не о нем.
    Рекомендую взять qemu, повесить на него дос, и из-под доса пробовать (учитывая, что в qemu есть встроенный дебужник, которым можно смотреть регистры, память и т.п. - вообще сказка), а уже потом переносить на 0 кольцо.
     
  12. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    Да, и еще. Надеюсь, есть понимание, что 0 кольцо<>DOS? А то вспомнил, что вы пытались там что-то с инт16 делать...
     
  13. clotho

    clotho New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2010
    Сообщения:
    21
    В нуль кольцо больше не выходит =С (зачем обновился?)
    Теперь тока драйвер писать?
     
  14. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
     
  15. Andrej

    Andrej New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2010
    Сообщения:
    4
    Я тоже копаюсь с клавой, в других ветвях этого форума нашел ответы на поставленный в данной теме вопрос, проверил все работает как часы. Являюсь полностью зеленым в Ассемблере, пытался докопаться что работает и как, не мог бы кто нибудь помочь и подкорректировать мои коменты? Вот код.
    Код (Text):
    1.  _asm {
    2.       pusha     ;пишет что-то в регистр ax ?
    3.       cli           ;отключает прерывание?              
    4.       mov dl, key       ;в регистр дл записывает значения аргумента, чтоб протом
    5.                 ;его передать через out? почему нельзя сразу там это сделать?
    6.  
    7.       mov ecx,10000h    ;счетчик для цикла, будет уменьшаться
    8.  
    9. WaitWhlFull:
    10.       in al, 64h        ;смотрим в нужный порт
    11.       test al, 1        ;пока первый бит равен 1 - продолжаем цикл
    12.       loopnz WaitWhlFull    ;цикл от метки WaitWhlFull: , каждый раз уменьшает есх пока аl = 1 или есх=0
    13.  
    14.       mov ecx,10000h    ;сбрасывает счеткик
    15.  
    16. TstCmdPortLp1:
    17.       in al, 64h
    18.       test al, 2        ;пока второй бит равен 1 ( 1 0 ) - продолжаем цикл
    19.       loopnz TstCmdPortLp1
    20. ;порт готов принимать информацию, пишем в порт
    21.       mov al, 0d2h
    22.       out 64h, al       ;пишем значение al в нужный порт микроконтроллера - метку о том, что работает кейборд
    23.       mov ecx,10000h
    24.  
    25. TstCmdPortLp2:
    26.       in al, 64h
    27.       test al, 2        ;2 потому что 0d2h?
    28.       loopnz TstCmdPortLp2  ; ждем пока информация поступит в порт?
    29.  
    30.       mov al, dl
    31.       out 60h, al           ;пишем значение сканкода кнопки
    32.  
    33.       sti       ;запрещает прерывание
    34.       popa  ;неясно мне) выбирает значение из стека?
    35.   }
    в данный момент я копаюсь с мышкой. Насколько я знаю вместо 0d2h надо вводить 0d3h, и посылать 4 байта сразу (если мышь с колесиком), по очереди? Инфы нашел в инете крайне мало. Первый байт несет инфу о кликах второй и третий о движении и четвертый о колесике. Мне нужен только первый. Никто не подскажет как корректно это сделать? Кроме 0d3h не надо тест проверки изменять?
     
  16. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    Andrej
    По работе отдельных команд читаем IA-32 SDM (качается с сайта интела, ВСЕ команды подробно описаны в томах 2А, 2В).
    Если читать лень - http://wasm.ru/forum/viewforum.php?id=23 - раздел для начинающих.

    По работе клавы:
    - "2 потому что 0d2h?" - нет, см. выше, я приводил код, там видно что проверяется в 64 порту и зачем.
    - "пишем значение al в нужный порт микроконтроллера - метку о том, что работает кейборд" - сами-то поняли, что написали? Я нет.
    - "ждем пока информация поступит в порт?" - ждем пока 8042 прожует команду и будет готов принять для нее данные.

    Из написанного текста и комментариев, кстати, абсолютно неясно, что вы пытаетесь сделать.
     
  17. Andrej

    Andrej New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2010
    Сообщения:
    4
    Цель моих пытаний :) - корректно сэмулировать нажатие мышки. Я нашел код который может заинтересовать автора темы, и который, я так понял, тоже не является профессионалом в ассемблере. Решил код закомментировать, но у меня мало компетенции для этого. В комментариях просто попытка разобраться что к чему ... теперь мне ясно что независимо от того, какая была команда 0d2h или 0d3h проверка на то можно ли писать в 60h (test al, 2) (прожевал ли 64h свою команду) не изменяется.
    Если просто заменить команду 0d2h на 0d3h и посылать сканкоды мышки - то мышь заклинивает. Если посылать по очереди несколько команд то мышка подвисает периодически но все равно сама ниче не делает, а еще клавиатурные светодиоды иногда мигают ... по-идее мышка посылает Несколько пакетов по очереди и они все вместе описывают состояние мышки. Посылает туда же, в кеборд контроллер 8042.
    А еще вычитал вот здесь http://ftp.utcluj.ro/pub/users/cemil/asm/CH20.pdf, что есть команда 0d4h - "Writes the next data byte (60h) to the mouse (auxiliary) device". Первое, что приходит на ум - первый байт писать после команды 0d3h, а потом еще два (или три если мышь с колесиком) после команды 0d4h. А может все писать после 0d4h? Может кто знает что к чему?
    Просто для меня все это необычно, так как мало опыта (я имею хороший опыт только в c++), и может я просто не понимаю элементарных принятых алгоритмов, а кому-то здесь "все и так ясно". Вечером, как вернусь с работы попробую реализовать эти свои две гипотезы ...
     
  18. Vic3Dexe

    Vic3Dexe New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2009
    Сообщения:
    53
    Дело не в опыте в ассемблере, асм - это инструмент, и, как и любой другой, постигается чтением мануала на него (IA-32 SDM).

    Решение же данной задачи к познаниям в асме не имеет ни малейшего отношения, т.к. нужно знать не асм, а работу связки 8042-клава-мышь (опять же, читаем спецификации). Короче говоря, отделяем алгоритм от его реализации и не путаем их. =)

    Также неплохо знать буржуйский, т.к. вот это вот
    отправит засунутый в 60 порт байт прямиком в мышЪ (ну или любой внешний девайс, воткнутый в мышиный порт). Оно ей (мыши) надо?

    Конкретно же по эмуляции действий мыши не подскажу, до работы с сим девайсом пока выше int 33h не поднялся (за ненадобностью). В качестве идеи могу посоветовать проанализировать посылки реальной мыши, а затем эмулировать их, предварительно вырубив настоящую (программно).
     
  19. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.561
    Адрес:
    Russia
    Vic3Dexe
    Дополню - это осуществляется перехватом векторов обработки прерываний мыши.
    Andrej
    Желательно вообще написать свои процедуры обработки. Полностью. Потом вызывая их вручную, получите эмуляцию. За одно поймете всю соль. Да, делать все это желательно в DOS (для образовательных целей).
    А так же попутно почитывая Кулакова "Программирование на аппаратном уровне". Про то как работают мышки. Для начала будет более чем достаточно.
     
  20. VaStaNi

    VaStaNi Member

    Публикаций:
    0
    Регистрация:
    1 июн 2004
    Сообщения:
    203
    Адрес:
    Ukraine
    ребят clotho и Andrej, с одной строны могу помочь, с другой лень и некогда отписывать и описывать... поэтому принял решение дать Вам готовые сорцы из своего проектика ОСи. То что Вы сейчас разгребаете интересное, полезное и трудное занятие требуещее кропотливости работы с устройствами + аккуратное. Сам прошёл десятки ребутов при оседлании KBC. Отлаживал и познавал под досом, чего и Вам желаю + маны вкуривать строго обязательно.
    Обязательно нужно усвоить, что клава и мышь для Вас это один и тот же KBC, вычитывание данных ИЗ которого вне зависимости клавные дела это или мышиные ПЕРВО-НАПЕРВО! Это собственно и есть готовность принимать Ваши приказы, т.к. вычитка порта 0x60 (и порой неоднократная!) дает возможность сразу засылать спецкоманды из манов....
    Короче вместо того чтобы пухнуть мозгами от ваших ваяний :0) попотейте Вы ))) но от рабочего и комментированного сурса 3-х обработчиков IRQ 0, 1, 12.
    Здесь Вам много лишнего может показаться, но дошедший мозгом до конца вкусит истинный дзен, факт! Рекомендую вкусить, хотябы находя ОТВЕТЫ на свои вопросы + пытливость типа "нафига именно так", поможет приподнять завесу над нюанасами.
    Рекомендую создать мониторинговую ДОСовкую прожку с этими инклудами и юзаньем ИМЕННО 3-х обработчиков в ней, НЕ советую отказываться от этого, т.к. несмотря на то, что они (т.е. именно все 3) работают в асинхронном временном так сказать континиуме, они выполняют ряд аппаратно-программных задач и фич, включая, например, перезапуск клавы, мыши, обслуга светодиодов клавы, чувствование смены мыши PS/2 на ходу (брехни что НЕЛЬЗЯ этого делать доказательство сии сорцы), вычитка ID мыши.... моного чего творил с ними лет 5 назад.
    При использовании в своих разработках ссылки на автора джентльменски приветствуются!
    Конечно там завязки на структурки имеются, но пытливым это не помеха, маны курить (знать) все одно надо...
    Итак, погнали.
    Таймерное, оно же системное у меня тюкает с частотой 1000Гц а не 18,2.... ну типа нУнА так и всё :)
    Код (Text):
    1. ALIGN  4
    2. IRQ_0:                  ; Системный таймер
    3.     push    ds
    4.     push    es
    5.     pushad
    6.     mov     eax, 0x20              ;сигнал EOI
    7.     mov     edx, eax
    8.     out     dx, al
    9.     mov     eax, SYS_VAR
    10.     mov     ds, ax
    11.     mov     es, ax
    12.     inc     [iTMR0.Cnt1000Hz]
    13.  
    14. ;----------------------------------------------------------
    15. ; проверка Буфера Клавиатуры
    16.  
    17.     mov     eax, [iKBD.HeadBuffWR]    ;
    18.     mov     edx, [iKBD.HeadBuffRD]     ;
    19.     cmp     eax, edx        ;
    20.      je     @emptyBuffKBD
    21.     mov     eax, [edx]          ; взять код символа из буфера клавиатуры
    22.     add     edx, 4
    23.     cmp     edx, iKBD.EndBuff
    24.      jc     @notEndBuffKBD
    25.     mov     edx, iKBD.StartBuff
    26. @notEndBuffKBD:
    27.     mov     [iKBD.HeadBuffRD], edx
    28.  
    29. ; символ из буфера клавиатуры взят в EAX
    30.  
    31.     cmp     al, 0x1B        ; = ESC = REBOOT !!!!
    32.      jne    @sysk
    33.     mov     al, 0xFE
    34.     out     0x64, al
    35.     jmp    @qqirq1
    36. @sysk:
    37.     cmp     al, "1"
    38.      jne  @1
    39.     push    eax
    40.     mov     eax, Melody1
    41.     jmp    @pMel
    42. @1:
    43.     cmp     al, "2"
    44.      jne  @2
    45.     push    eax
    46.     mov     eax, Melody2
    47.     jmp    @pMel
    48. @2:
    49.     cmp     al, "3"
    50.      jne  @3
    51.     mov     eax, Melody3
    52.     push    eax
    53.     jmp    @pMel
    54. @3:
    55.     cmp     al, "4"
    56.      jne  @4
    57.     push    eax
    58.     mov     eax, Melody4
    59.     jmp    @pMel
    60. @4:
    61.  
    62.     cmp     al, "5"
    63.      jne  @5
    64.     push    eax
    65.     mov     eax, Melody5
    66.     jmp    @pMel
    67. @5:
    68.     cmp     al, "6"
    69.      jne  @6
    70.     push    eax
    71.     mov     eax, Melody6
    72.     jmp    @pMel
    73. @6:
    74.     cmp     al, "7"
    75.      jne  @7
    76.     push    eax
    77.     mov     eax, Melody7
    78.     jmp    @pMel
    79. @7:
    80.     cmp     al, "8"
    81.      jne  @8
    82.     push    eax
    83.     mov     eax, Melody8
    84.     jmp    @pMel
    85. @8:
    86.     cmp     al, "9"
    87.      jne  @9
    88.     push    eax
    89.     mov     eax, Melody9
    90.     jmp    @pMel
    91. @9:
    92.     cmp     al, "0"
    93.      jne  @10
    94.     push    eax
    95.     mov     eax, Melody10
    96. @pMel:
    97.     mov     bx, SYS_TXT_RING0
    98.     call    SetNewLineNotes
    99.     pop     eax
    100.     jmp    @qqirq1
    101.  
    102. @10:
    103.     cmp     al, " "
    104.      jne    @qqirq1
    105.     push    eax
    106.     call    StopNote
    107.     pop     eax
    108.  
    109. ;        mov     edi, 0x18A00
    110. ;        mov     ax, cs
    111. ;        call    printHexDword
    112. ;        add     edi, 2
    113. ;        mov     eax, @@1
    114. ;        call    printHexDword
    115. ;        add     edi, 2
    116. ;        pushfd
    117. ;        pop     eax
    118. ;        call    printHexDword
    119.  
    120. ;        mov     eax, 0x01020304
    121. ;        xor     ebx, ebx
    122. ;        div     ebx
    123. ;@@1:
    124. ;        mov    es, bx
    125. ;        mov    [es:0], al
    126. ;        jmp    @qqirq1
    127. ;;;;;;;;;;;;;;;;;;;;;;;;
    128. @qqirq1:
    129.     mov     edi, 0x18140
    130.     call    printHexDword
    131. @emptyBuffKBD:
    132. ;----------------------------------------------------------
    133.  
    134.     mov     ebp, [iTMR0.Cnt1000Hz]
    135.  
    136. ; выполнение следущих процедур по такту 1000 Гц
    137.  
    138.     call    @TickTimer0
    139.  
    140. ;----------------------------------------------------------
    141.  
    142.     dec     [iTMR0.Cnt4Hz]
    143.      jne    @restMousePS2
    144.  
    145. ; получаем тут периодичность входа 4 раза в секунду
    146. ; проверка флагов и пошаговая подготовка реинициализации клавиатуры
    147.  
    148.     dec     [iKBD.CntStatCnct]      ; уменьшим счетчик-флаг отключения клавиатуры
    149.     mov     ebx, [iKBD.CntStatCnct] ; уменьшим счетчик-флаг отключения клавиатуры
    150.      jne    @stp2RestKBD
    151. @repRestKBD:
    152.     mov     [iKBD.CntStatCnct], Cnt1RestKBD ; общий счетчик процесса рестарта клавиатуры
    153.     mov     dword [iKBD.ByteID], 0x020000FF ; активация ловушки ID байт
    154.     mov     [iKBD.HeadBuffWR], iKBD.StartBuff ; инициализация циклического буфера клавиатуры
    155.     mov     [iKBD.HeadBuffRD], iKBD.StartBuff
    156.     mov     ax, 0x64AD          ; выключим клавиатуру и ее прерывания
    157.     jmp    @AddNewCmdKBC
    158.  
    159. @stp2RestKBD:
    160.     cmp     ebx, Cnt2RestKBD
    161.      jne    @stp3RestKBD
    162.     mov     ax, 0x64AE          ; включим клавиатуру и ее прерывания в KBC
    163.     call    AddNewCmdKBC        ; поместим в очередь команду
    164.     mov     ax, 0x60FF          ; сброс клавиатуры
    165.     jmp    @AddNewCmdKBC
    166.  
    167. @stp3RestKBD:
    168.     cmp     ebx, Cnt3RestKBD
    169.      jne    @stp4RestKBD
    170.     mov     word [iKBD.ByteID], 0x00FF ; активация ловушки ID байт
    171.     mov     ax, 0x60F4          ; код команды включения клавиатуры
    172.     call    AddNewCmdKBC        ; поместим в очередь команду
    173.     mov     al, [iKBD.StatSwitch]   ; восстановим текущее рабочее состояние светодиодной индикации клавиатуры
    174.     call    SetLEDsKBD
    175.     jmp    @nonNewTaskKBC
    176.  
    177. @stp4RestKBD:
    178.     cmp     ebx, Cnt4RestKBD
    179.      jne    @echoKBD
    180.     cmp     [iKBD.PrefixCode], 0    ; клавиатура уже отвечает ?
    181.      je     @repRestKBD         ; Нет, повторить сброс
    182.     mov     ax, 0x60F3          ; код команды установки параметров клавиатуры
    183.     call    AddNewCmdKBC
    184.     mov     al, [iKBD.Setting]      ; загрузим текущие установки параметров клавиатуры
    185.     and     al, 0x7F        ; бит 7 = 0
    186.     call    AddNewCmdKBC        ; поместим в очередь команду
    187.     mov     ax, 0x60F2          ; код команды чтения ID байт клавиатуры
    188.     jmp    @AddNewCmdKBC
    189.  
    190. @echoKBD:
    191.     cmp     ebx, CntEchoKBD
    192.      jnc    @nonNewTaskKBC
    193.     mov     ax, 0x60EE          ; коды порта и команды эха клавиатуры
    194.     jmp    @AddNewCmdKBC
    195.  
    196. ;----------------------------------------------------------
    197.  
    198. ; проверка флагов и пошаговая подготовка реинициализации Mouse PS/2
    199.  
    200. @restMousePS2:
    201.     cmp     [iTMR0.Cnt4Hz], 0x80
    202.      jne    @nonNewTaskKBC
    203.     dec     [iMOUSE_PS2.StatCnct]
    204.     mov     ebx,[iMOUSE_PS2.StatCnct]
    205.      jne    @stpReset0MousePS2
    206.     mov     [iMOUSE_PS2.StatCnct], CntRestMouse
    207.     mov     [iMOUSE_PS2.CntNxtReset], CntResetMouse
    208.     mov     [iMOUSE_PS2.PozNxtTstRate], dword iMOUSE_PS2.LineTstRate
    209.     mov     [iMOUSE_PS2.HeadBuff], dword iMOUSE_PS2.ReciveDump  ; голову указателя буфера в начало
    210.     mov     [iMOUSE_PS2.WaitByteID], 0xFF
    211.     mov     [iMOUSE_PS2.ByteID], 0xFF
    212.     mov     [iMOUSE_PS2.CntPacket], 0
    213.     mov     ax, 0x64A7          ; выключим мышь
    214.     call    AddNewCmdKBC        ; поместим в очередь команду
    215.     inc     eax             ;= 0x64A8 включим мышь
    216.     jmp    @AddNewCmdKBC
    217.  
    218. @stpReset0MousePS2:
    219.     cmp     ebx, [iMOUSE_PS2.CntNxtReset]
    220.      jne    @stpNxtNumRateMousePS2
    221. @stpReset1MousePS2:
    222.     mov     [iMOUSE_PS2.WaitByteID], 0xFF
    223.     mov     [iMOUSE_PS2.ByteID], 0xFF
    224.     mov     [iMOUSE_PS2.CntPacket], 0
    225.     mov     [iMOUSE_PS2.LenPacket], 0
    226.     mov     ax, 0x64D4
    227.     call    AddNewCmdKBC
    228.     mov     ax, 0x60FF
    229. ;        dec     ebx
    230. @IncNumRate:
    231.     dec     ebx
    232.     mov     [iMOUSE_PS2.CntNumRate], ebx
    233.     jmp    @AddNewCmdKBC
    234.  
    235. @stpNxtNumRateMousePS2:
    236.     cmp     ebx, [iMOUSE_PS2.CntNumRate]
    237.      jne    @stpSettingMousePS2
    238.     mov     ax, 0x64D4
    239.     call    AddNewCmdKBC
    240.     mov     ax, 0x60F3
    241.     call    AddNewCmdKBC
    242.     mov     ax, 0x64D4
    243.     call    AddNewCmdKBC
    244.     mov     esi, [iMOUSE_PS2.PozNxtTstRate]
    245.     mov     ax, [esi]
    246.     inc     esi
    247.     cmp     ah, 0xFE
    248.      jne    @pokeNewRate
    249.     inc     esi
    250.     mov     ah, [esi]
    251.     inc     esi
    252.     mov     [iMOUSE_PS2.WaitByteID], ah ; ожидаемый байт ID от мыши
    253.     mov     [iMOUSE_PS2.StatCnct], Cnt0SettingMouse + 1
    254.     cmp     byte [esi], 0
    255.      je    @endTabRate
    256.     dec     [iMOUSE_PS2.StatCnct]  ; = Cnt0SettingMouse
    257. @endTabRate:
    258.     inc     ebx
    259.     mov     [iMOUSE_PS2.CntNxtReset], ebx
    260. @pokeNewRate:
    261.     mov     [iMOUSE_PS2.PozNxtTstRate], esi
    262.     mov     ah, 0x60
    263.     jmp    @IncNumRate
    264.  
    265. @stpSettingMousePS2:
    266.     cmp     ebx, Cnt0SettingMouse
    267.      je     @pokeSetting
    268.     cmp     ebx, Cnt1ReadIDmouse
    269.      je     @pokeCmdReadIDmousePS2
    270.     cmp     ebx, Cnt1SettingMouse
    271.      jne    @stpReadIDmousePS2
    272.     mov     al, [iMOUSE_PS2.ByteID]
    273.     cmp     al, [iMOUSE_PS2.WaitByteID]
    274.      je     @pokeSetting
    275.     mov     ebx, [iMOUSE_PS2.CntNxtReset]
    276.     mov     [iMOUSE_PS2.StatCnct], ebx
    277.     jmp    @stpReset1MousePS2
    278.  
    279. @pokeSetting:
    280.     mov     ax, 0x64D4
    281.     call    AddNewCmdKBC
    282.     mov     ax, 0x60F5
    283.     call    AddNewCmdKBC
    284.     mov     ax, 0x64D4
    285.     call    AddNewCmdKBC
    286.     mov     ax, 0x60E8
    287.     call    AddNewCmdKBC
    288.     mov     ax, 0x64D4
    289.     call    AddNewCmdKBC
    290.     mov     ah, 0x60
    291.     mov     al, [iMOUSE_PS2.Setting] ; 8 count/mm
    292.     push    eax
    293.     and     al, 3
    294.     call    AddNewCmdKBC
    295.     mov     ax, 0x64D4
    296.     call    AddNewCmdKBC
    297.     pop     eax
    298.     shr     al, 2
    299.     and     al, 1
    300.     or      al, 0xE6  ; = 0x60E7 = 2:1
    301.     call    AddNewCmdKBC
    302.     mov     ax, 0x64D4
    303.     call    AddNewCmdKBC
    304.     mov     ax, 0x60F3
    305.     call    AddNewCmdKBC
    306.     mov     ax, 0x64D4
    307.     call    AddNewCmdKBC
    308.     mov     ah, 0x60
    309.     mov     al, [iMOUSE_PS2.UserRate]
    310.     mov     [iMOUSE_PS2.StatCnct], Cnt2ReadIDmouse
    311.     jmp    @AddNewCmdKBC
    312.  
    313. @stpReadIDmousePS2:
    314.     cmp     ebx, Cnt2ReadIDmouse
    315.      jnc    @nonNewTaskKBC
    316. @pokeCmdReadIDmousePS2:
    317.     mov     ax, 0x64D4
    318.     call    AddNewCmdKBC
    319.     mov     ax, 0x60F4
    320.     call    AddNewCmdKBC
    321.     mov     ax, 0x64D4
    322.     call    AddNewCmdKBC
    323.     mov     ax, 0x60F2
    324.     mov     [iMOUSE_PS2.ByteID], al ; = 0xF2
    325. @AddNewCmdKBC:
    326.     call    AddNewCmdKBC
    327. @nonNewTaskKBC:
    328.  
    329. ;----------------------------------------------------------
    330. ; разбор очереди команд контроллера клавиатуры-мыши PS/2
    331. ;----------------------------------------------------------
    332.  
    333.     mov     bx, [iTMR0.FlagTskTmr]  ; читаем флаги таймерных задач по такту 100Гц
    334.     or      bx, bx          ; есть какие либо таймерные системные задачи ?
    335.      je     @nonCmdKBC          ; Нет, переход по метке
    336.     test    bx, FlagCmdKBC      ; есть задачи работы с командами для KBC клавиатуры и мыши PS/2 ?
    337.      je     @nonCmdKBC          ; Нет, переход по метке
    338.     mov     esi, [iKBC.HeadCmdKBC]  ; берем адрес головы строки команд
    339.     in      al, 0x64        ; читаем статус состояния контроллера клавиатуры и мыши PS/2
    340.     test    al, 2           ; имеется ли готовность принять команды ?
    341.      jne    @nonCmdKBC          ; Нет, переход по метке
    342.     mov     ax, [ esi ]         ; берем в AX очередную команду, для выполнения
    343.     cmp     ax, 0x64D4          ; это команда назначена для мыши PS/2 ?
    344.      jne    @pokeCmdKBC
    345.     cmp     [iMOUSE_PS2.CntPacket], 0  ; мышь PS/2 генерирует информационный пакет ?
    346.      jne    @nonCmdKBC
    347. @pokeCmdKBC:
    348.     xor     dx, dx          ; DX = 0
    349.     mov     dl, ah          ; DX = адрес порта вывода для команды(данных) (это 60h либо 64h)
    350.     out     dx, al          ; поместим в порт контроллера AL байт
    351.     cmp     ax, 0x64AE          ; требуется включить клавиатуру ?
    352.      jne    @non64AE
    353.     in      al, 0x21
    354.     and     al, 0xFD
    355.     out     0x21, al
    356.     jmp    @nxtStepCmdKBC
    357. @non64AE:
    358.     cmp     ax, 0x64AD          ; требуется выключить клавиатуру ?
    359.      jne    @non64AD
    360.     in      al, 0x21
    361.     or      al, 2           ; маскировать IRQ1
    362.     out     0x21, al
    363.     jmp    @nxtStepCmdKBC
    364. @non64AD:
    365.     cmp     ax, 0x64A8          ; требуется включить клавиатуру ?
    366.      jne    @non64A8
    367.     in      al, 0xA1
    368.     and     al, 0xEF
    369.     out     0xA1, al
    370.     jmp    @nxtStepCmdKBC
    371. @non64A8:
    372.     cmp     ax, 0x64A7
    373.      jne    @nxtStepCmdKBC
    374.     in      al, 0xA1
    375.     or      al, 0x10        ; маскировать IRQ12
    376.     out     0xA1, al
    377. @nxtStepCmdKBC:
    378.     add     esi, 2          ; переместим указатель головы на следующий шаг очереди команд
    379.     cmp     esi, [iKBC.EndCmdKBC]   ; следующая команда пустая т.е. очередь вычерпана ?
    380.      jne    @nonStepCmdKBC      ; Нет, переход на сохранение текущего адреса головы очереди команд
    381.     and     [iTMR0.FlagTskTmr], not FlagCmdKBC ; сброс флага наличия команд клавиатуры и мыши PS/2
    382.     mov     esi, iKBC.LineCmdKBC    ; установка указателя головы в начальное состояние
    383.     mov     [iKBC.EndCmdKBC], esi   ; сохранить текущий адрес головы строки команд
    384. @nonStepCmdKBC:
    385.     mov     [iKBC.HeadCmdKBC], esi  ; сохранить текущий адрес головы строки команд
    386. @nonCmdKBC:
    387. ;----------------------------------------------------------
    388.     popad
    389.     pop     es
    390.     pop     ds
    391.        IRET
    Клавка вкусняшка, между прочим :)
    Код (Text):
    1. ALIGN  4
    2. IRQ_1:
    3.     push    ds
    4.     push    eax
    5.     push    ebx
    6.     push    edx
    7.     xor eax, eax
    8.     xor ebx, ebx
    9.     in  al, 0x60        ; читаем порт клавиатуры
    10.     push    eax
    11.     mov eax, 0x20
    12.     mov edx, eax
    13.     out dx, al
    14.     mov eax, SYS_VAR
    15.     mov ds, ax
    16.     mov edx, iKBD.PrefixCode
    17.     pop eax
    18.     mov ah, al
    19.     cmp [iKBD.ByteID], 0xFF ; > 0 ?  ловушка используется ?
    20.      je @waitID
    21.     mov [iKBD.CntStatCnct], CntWatchDogKBD ; взводим антизависатор, т.к. клавиатура функционирует нормально!
    22.     cmp al, 0xEE        ; принят тестовый байт эха ?
    23.      jnc    @UpcodEE
    24.     cmp byte [edx], 0xE1    ; это признак работы с кодами клавиши "Pause" ?
    25.      je @DoKeyPause     ; Да, переход на обработчик кодов "Pause"
    26.  
    27.     cmp byte [edx], 0xE0    ; это признак работы с 2x байтными кодами ?
    28.      je @DoDoubleCode       ; Да, переход на обработчик уникального второго байта
    29.     cmp al, 0xE0        ; это первый байт 2х байтного кода клавиши ?
    30.      je @SavePrefixCode     ; Да, переход и фиксация байта 0xE0, как префикса-сигнатуры
    31.     cmp al, 0xE1        ; это первый байт исключительных байт кода для "Pause" ?
    32.      jne    @nonFixCode     ; Нет, переход дальше
    33. ; Да, переход  и фиксация байта 0xE1 как префикса-сигнатуры этого исключения
    34. @SavePrefixCode:            ; сохранение префикса
    35.     mov [edx], al       ; фиксируем код в [PrefixCode]
    36.     jmp    @nonUseCode
    37.  
    38. @waitID:
    39.     cmp byte [edx], 0xAB    ; PrefixCode
    40.      je @saveID
    41.     cmp al, 0xAB        ; это второй сигнатурный байт-префикс ? (перед ID байтами)
    42.      je @SavePrefixCode
    43.     cmp al, 0xFA        ; принят байт эха клавиатуры ?
    44.      je @SavePrefixCode
    45.     jmp    @nonUseCode      ; код не используется вообще, выход!
    46.  
    47. @saveID:
    48.     mov [iKBD.ByteID], al   ; запомним ID байт
    49.     mov [edx], bl       ; обнулим [PrefixCode]
    50.     jmp    @nonUseCode
    51.  
    52. @UpcodEE:
    53.     cmp al, 0xFE        ; принят байт признака отключения клавиатуры ?
    54.      jne    @nonUseCode     ; Нет, значит байт не использовать вообще
    55.     mov [iKBD.ByteID], 0xFF ; = 0 активация ловушки ID байт
    56.     mov [iKBD.CntStatCnct], 1   ; принудительно делаем реинициализацию клавиатуры
    57.     jmp    @nonUseCode      ; код не используется вообще, выход!
    58.  
    59. @DoKeyPause:
    60.     cmp al, 0x45        ; нажатие "Pause" ?
    61.      je @trfrmCodePause
    62.     cmp al, 0xC5        ; отжатие "Pause" ?
    63.      jne    @nonUseCode
    64. @trfrmCodePause:
    65.     mov [edx], bl       ; установим [PrefixCode] = 0 -- признак однобайтного формата
    66.     and al, 0x80        ; трансформация в эквивалентные коды 0x00/0x80
    67.     jmp    @ReadCodeMap1        ; теперь работаем с символьными кодами таблицы перекодировки
    68.  
    69. @DoDoubleCode:
    70.     mov [edx], bl       ; установим [PrefixCode] = 0 -- признак однобайтного формата
    71.     inc edx         ; теперь ESI указывает на [StatDopKeys]
    72.     test    al, 0x80        ; это нажатие?
    73.      je @n1UPkey        ; если да, переход
    74.     mov [iKBD.LastSwKey], bl    ; сброс фиксации кода последней нажатой доп-клавиши...
    75. @n1UPkey:
    76.     and al, 0x7F        ; удалим различие кодов нажития и отжатия (приравнивание)
    77.     cmp al, 0x2A        ; это обрамляющие байты 4х байтных посылок скан-кода ?
    78.      je @nonUseCode     ; если да, то код не используется вообще, выход!
    79.     mov bl, CORR_TAB2       ; константа для коррекции и компактности прилегающих таблиц перекодировки скан-кодов 1й и 2й
    80.     mov al, 8           ; AL = 8 как маска бита статуса для левого "WIN"
    81.     cmp ah, 0x5B        ; нажат ли левый "WIN" ?
    82.      je @saveStByte
    83.     cmp ah, 0xDB        ; отжат ли левый "WIN" ?
    84.      je @clrStByte
    85.     mov al, 128         ; AL = 128 как маска бита статуса для правого "WIN"
    86.     cmp ah, 0x5C        ; нажат ли правый "WIN" ?
    87.      je @saveStByte
    88.     cmp ah, 0xDC        ; отжат ли правый "WIN" ?
    89.      je @clrStByte
    90.     mov al, 32          ; AL = 32 как маска бита статуса для правого "CTRL"
    91.     cmp ah, 0x52        ; это нажата клавиша "Insert" ?
    92.      jne    @chkDopKey
    93.     mov al, 4           ; AL = 4 -- бит 4 в [StatSwitch] для "Insert"
    94.     inc edx         ; теперь ESI указывает на [StatSwitch]
    95. @chgStByte:             ; изменим состояние переключателя
    96.     cmp ah, [iKBD.LastSwKey]    ; она уже нажата и в удержании?
    97.      je @nonUseCode     ; если да, то код не используется вообще, выход!
    98.     mov [iKBD.LastSwKey], ah    ; сброс фиксации кода последней нажатой доп-клавиши...
    99.     push    eax
    100.     xor ah, ah
    101.     btc word [edx], ax      ; изменим на противоположное состояние бит номер AX в StatSwitch
    102.     or  byte [edx], 0x80    ; установим флаг изменения индикаторов LEDs
    103.     pop eax
    104.     jmp    @ReadCodeMap1        ; теперь работаем с символьными кодами таблицы перекодировки
    105.  
    106. @nonFixCode:
    107. ; значит это однобайтный скан-код, который в AH, а AL = 0
    108.     test    ah, 0x80
    109.      je @n2UPkey
    110.     mov [iKBD.LastSwKey], bl
    111. @n2UPkey:
    112.     inc edx         ; теперь ESI указывает на [StatDopKeys]
    113.     inc eax         ; AL = 1 как маска бита статуса для левого "SHIFT"
    114.     cmp ah, 0x2A        ; нажат ли левый "SHIFT" ?
    115.      je @saveStByte
    116.     cmp ah, 0xAA        ; отжат ли левый "SHIFT" ?
    117.      je @clrStByte
    118.     mov al, 16          ; AL = 16 как маска бита статуса для правого "SHIFT"
    119.     cmp ah, 0x36        ; нажат ли правый "SHIFT" ?
    120.      je @saveStByte
    121.     cmp ah, 0xB6        ; отжат ли правый "SHIFT" ?
    122.      je @clrStByte
    123.     mov al, 2           ; AL = 2 как маска бита статуса для левого "CTRL"
    124. @chkDopKey:
    125.     cmp ah, 0x1D        ; нажат ли какой либо "CTRL" ?
    126.      je @saveStByte
    127.     cmp ah, 0x9D        ; отжат ли какой либо "CTRL" ?
    128.      je @clrStByte
    129.     add al, al
    130.     cmp ah, 0x38        ; нажат ли какой либо "ALT" ?
    131.      jne    @nonDownALT
    132. @saveStByte:                ; установка бита по маске в AL
    133.     cmp ah, [iKBD.LastSwKey]
    134.      je @nonUseCode
    135.     mov [iKBD.LastSwKey], ah
    136.     or  byte [edx], al      ; установим нужный бит статуса в StatDopKeys
    137.     jmp    @ReadCodeMap1        ; теперь работаем с символьными кодами таблицы перекодировки
    138.  
    139. @clrStByte:             ; сброс бита по маске в AL
    140.     not al
    141.     and byte [edx], al      ; обнулим нужный бит статуса в StatDopKeys
    142.     jmp    @ReadCodeMap1
    143.  
    144. @nonDownALT:
    145.     cmp ah, 0xB8        ; отжат ли какой либо "ALT" ?
    146.      je @clrStByte
    147. ;.............................
    148. ; проверим нажатие и изменяем состояния статусов клавиш переключателей:
    149. ; "Scroll Lock",  "Num Lock",  "Caps Lock"
    150. ;.............................
    151.     inc edx         ; ESI указывает на байт состояния переключателей
    152.     xor al, al          ; AL = 0 -- бит 0 в [StatSwitch]
    153.     cmp ah, 0x46        ; нажат ли "Scroll Lock" ?
    154.      je @chgStByte
    155.     inc eax         ; AL = 1 -- бит 1 в [StatSwitch]
    156.     cmp ah, 0x45        ; нажат ли "Num Lock" ?
    157.      je @chgStByte
    158.     inc eax         ; AL = 3 -- бит 2 в [StatSwitch]
    159.     cmp ah, 0x3A        ; нажат ли "Caps Lock" ?
    160.      je @chgStByte
    161.  
    162. @ReadCodeMap1:              ; собственно чтение кода клавиши из таблицы посредством смещения в AH=полученному скан-коду клавиатуры
    163.     mov al, ah
    164.     test    [iKBD.Setting], 0x80    ; бит 7 установлен ?  КЛИК используется ?
    165.      je @nonCLICK
    166.     cmp [iSPK.AdrLineNotes], 0
    167.      jne    @nonCLICK
    168.     test    al, 0x80        ; это код нажатия ?
    169.      jne    @nonCLICK
    170.     mov edx, [iSPK.AdrClicKEYs]
    171.     mov [iSPK.AdrLineNotes], edx
    172.     mov dx, [iSPK.SegClicKEYs]
    173.     mov [iSPK.SegLineNotes], dx
    174.     mov dword [iSPK.CntDelayNote], 1
    175. @nonCLICK:
    176.     push    eax         ; важно сохраненить AL
    177.     and al, 0x7F        ; обнуляем бит 7, погасив признак отжатия
    178.     movzx   eax, al         ; EAX = смещение в таблице символьных кодов
    179.     mov edx, iKBD.KEYsCodeMap   ; ESI указывает на таблицу кодов для однобайтных скан-кодов клавиш
    180.     add edx, eax        ; ESI = адрес со смещением от начала на величину скан-кода
    181.     add edx, ebx        ; ESI = адрес с дополнительным смещением если скан-код был с началом 0xE0
    182.     pop eax         ; восстановить AL
    183.     not ax          ; инвертировать биты AL
    184.     and ax, 0x80        ; в AL выделяем 7й бит, будет = "1" при нажатой клавише
    185.     or  ax, word [iKBD.StatDopKeys]  ; дополним статусами вспомогательных клавиш и переключателей
    186.     btr word [iKBD.StatDopKeys], 15  ; было ли изменение переключателей ?
    187.      jnc    @nonChangeLEDs      ; Нет, игнорируем новую установку LEDs
    188.     cmp [iSPK.LedStat], byte 0  ; работает ли иллюминация клавиатуры ?
    189.      jne    @nonChangeLEDs      ; Да, игнорируем новую индикацию LEDs
    190.     mov ebx, [iKBC.EndCmdKBC]   ; берем адрес конца строки команд
    191.     mov [ebx], dword 0x600060ED ; помещаем в очередь команду и данные LEDs для выполнения контроллером клавиатуры
    192.     mov [ebx+2], ah     ; поместим статусы переключателей в очередь
    193.     and [ebx+2], byte 7     ; обязательно обнулим лишние биты
    194.     add [iKBC.EndCmdKBC], 4 ; новая позиция конца очереди команд
    195.     or  [iTMR0.FlagTskTmr], FlagCmdKBC  ; выставим флаг обработки строки соманд клавиатуры
    196. @nonChangeLEDs:
    197.     shl eax, 8          ; смещаем все биты вверх на байт
    198.     mov al, [edx]       ; читаем код клавиши по фактическому адресу таблицы
    199.  
    200. ; AL = код клавиши
    201. ; AH - бит 7 нажатие/отжатие = "1"/"0" данной клавиши,
    202. ;      биты 5..0 из [StateShiftCtrlAlt] т.е. статусы вспомогательных клавиш
    203. ; 24..16 биты EAX = [StateSwitchKBD]  т.е. статусы переключателей
    204.  
    205.     mov edx, [iKBD.HeadBuffWR]
    206.     mov [edx], eax      ; помещаем в буффер новый код символа
    207.     add edx, 4
    208.     cmp edx, iKBD.EndBuff
    209.      jc @nonEndBuffKBD
    210.     mov edx, iKBD.StartBuff
    211. @nonEndBuffKBD:
    212.     mov [iKBD.HeadBuffWR], edx
    213. @nonUseCode:                ; "ХОЛОСТОЙ" выход из процедуры
    214.     pop edx
    215.     pop ebx
    216.     pop eax
    217.     pop ds
    218.        IRET
    Зверюга гызун живёт здесь ;)
    Код (Text):
    1. ALIGN  4
    2. IRQ_12:
    3.     push    ds
    4.     pushad
    5.     in      al, 0x60        ; читаем из KBC очередной байт от мыши!
    6.     push    eax
    7.     mov     eax, 0x20            ; EIO
    8.     mov     edx, eax
    9.     out     0xA0, al
    10.     out     dx, al
    11.     mov     eax, SYS_VAR
    12.     mov     ds, ax
    13.     pop     eax
    14.     cmp     [iMOUSE_PS2.CntPacket], 0 ; это начало нового пакета от мыши? (т.е. первый из трех?)
    15.      jne    @save           ; нет, значит это продолжение приема пакета, только сохраняем
    16.     cmp     [iMOUSE_PS2.StatCnct], Cnt2ReadIDmouse + 1
    17.      jc     @CheckByteID
    18.     cmp     [iMOUSE_PS2.StatCnct], CntWatchDogMouse + 1
    19.      jc     @chkAskByte
    20. @CheckByteID:
    21.     cmp     al, 9
    22.      jnc    @q
    23.     cmp     [iMOUSE_PS2.ByteID], 0xF2
    24.      jne    @q
    25.     mov     [iMOUSE_PS2.ByteID], al
    26.     cmp     [iMOUSE_PS2.StatCnct], Cnt2ReadIDmouse
    27.      jnc    @q
    28.     mov     [iMOUSE_PS2.StatCnct], CntWatchDogMouse
    29.     mov     [iMOUSE_PS2.WaitByteID], al
    30.     mov     ah, 6
    31.     cmp     al, 8
    32.      je     @FixLenPacket
    33.     mov     ah, 4
    34.     cmp     al, ah
    35.      je     @FixLenPacket
    36.     cmp     al, 3
    37.      je     @FixLenPacket
    38.     dec     ah            ; = 3
    39. @FixLenPacket:
    40.     mov     [iMOUSE_PS2.LenPacket], ah
    41.     jmp    @q
    42.  
    43. @chkAskByte:
    44.     cmp     al, 0xFA
    45.      jne    @qcmp           ; это префикс-байт "служебного" ответа, игнорируем
    46.     mov     [iMOUSE_PS2.StatCnct], CntWatchDogMouse
    47.     jmp    @q
    48. @qcmp:
    49.     jnc    @q
    50. ;@firstByte:
    51. ; проверим структурку первого байта пакета на правильность
    52. ; и отсутствие переполнения счетчиков перемещения X и Y
    53.     mov     ah, al
    54.     and     ah, 0xC8        ; выделим биты переполнения и бит признака
    55.     cmp     ah, 8           ; "правильный" первый байт пакета теперь всегда должен быть = 8
    56.      jne    @q              ; иначе бракуем, считая ложным!
    57. ; очень вероятно что в AL "правильный" первый байт пакета от мыши
    58.     mov     dl, [iMOUSE_PS2.LenPacket]
    59.     mov     [iMOUSE_PS2.CntPacket], dl ;
    60. @save:
    61.     mov     [iMOUSE_PS2.StatCnct], CntWatchDogMouse
    62.     mov     edi, [iMOUSE_PS2.HeadBuff] ; возьмем текущий указатель
    63.     mov     [edi], al           ; сохраним очередной принятый байт
    64.     inc     edi
    65.     mov     [iMOUSE_PS2.HeadBuff], edi ; сохраним новый указатель головы буфера
    66.     dec     [iMOUSE_PS2.CntPacket]  ; уменьшим количество принятых пакета
    67.      jne    @q
    68.     mov     [iMOUSE_PS2.HeadBuff], dword iMOUSE_PS2.ReciveDump  ; голову указателя буфера в начало
    69.  
    70. ; выяснить статусы и координаты мыши
    71.  
    72.     mov     esi, iMOUSE_PS2.ReciveDump ; начало буфера приема
    73.     mov     edi, iMOUSE_PS2.Buttons ; указатель на текущую координату X мыши
    74.     xor     eax, eax
    75.     xor     ebx, ebx
    76.     mov     al, [esi]           ; возьмем первый байт пакета
    77.     mov     bl, [esi+3]         ; возьмем четвертый байт пакета (колесо)
    78.     cmp     [iMOUSE_PS2.WaitByteID], 4
    79.      jne    @noID4
    80.     mov     ah, bl
    81.     and     bl, 0x0F        ; выделить биты-параметры поворота колес
    82.     and     ah, 0x30        ; выделить статусы дополнительных двух кнопок
    83.     jmp    @memNewZ
    84. @noID4:
    85.     cmp     [iMOUSE_PS2.WaitByteID], 3
    86.      jne    @saveButtons
    87.  
    88. @memNewZ:
    89.     mov     [iMOUSE_PS2.Z], bx
    90. @saveButtons:
    91.     inc     esi
    92.     mov     bl, al          ; сохраним оригинальное значение в BL
    93.     and     al, 0xF         ; выделить статусы кнопок и бит признака
    94.     or      al, ah
    95.     mov     [edi], al           ; сохранить статусы кнопок в [Buttons]
    96.     inc     edi
    97.     xor     eax, eax
    98.     mov     al, [esi]           ; взять 8 бит счетчика приращения X
    99.     inc     esi
    100.     or      al, al          ; имеется изменение по оси X ?
    101.      je     @calcMouseY         ; если нет, то перейдем к разбору по Y
    102. ; определим новую X позицию мыши
    103.     mov     bp, [edi]           ; возьмем в BP текущую координату из [_X_Mouse]
    104.     mov     dx, word [iMOUSE_PS2.X_Zoom] ; взять масштабный коэффициент мыши по X
    105.     test    bl, 0x10        ; каков знак X приращения ?
    106.      je     @pozitivX           ; преход по метке, если положительный
    107.     not     al              ; т.к. негативное перемещение инвертируем величину приращения
    108.     inc     ax              ; корреккция на 1
    109.     mul     dl              ; учтем масштабный коэффициент перемещения по X
    110.     xchg    ax, bp          ; развернули для удобства действий
    111.     sub     ax, bp          ; вычтем и получим новую координату X
    112.      jnc    @memNewX        ; перебор за ноль ?
    113.     xor     ax, ax          ; это так, поэтому делаем X = 0
    114. @memNewX:
    115.     mov     [edi], ax           ; сохранить новую координату в [_X_Mouse]
    116.     add     edi, 2
    117.     jmp   @calcMouseY           ; перейдем к определению Y координаты
    118.  
    119. @pozitivX:
    120.     mul     dl              ; учтем масштабный коэффициент перемещения по X
    121.     add     ax, bp          ; прирастим и получим новую координату X
    122.     cmp     ax, [iSCREEN.With]      ; нет ли теперь выхода за правую границу экрана?
    123.      jc     @memNewX        ; если нет, то переход на сохранение нового значения X
    124.     add     edi, 2          ; ничего не сохраняем, т.к. текущая координата X мыши уже на краю экрана, просто корректировка указателя
    125.  
    126. ; определим новую Y позицию мыши
    127. @calcMouseY:
    128.     xor     ax, ax
    129.     mov     al, [esi]           ; взять 8 бит счетчика приращения Y
    130.     inc     esi
    131.     or      al, al          ; имеется изменение по оси Y ?
    132.      je     @calcRET        ; если нет, то обходим разбор Y
    133. ;       тут EDI уже указывает на координату [_Y_Mouse]
    134.     mov     bp, [edi]           ; возьмем в BP текущую координату из [_Y_Mouse]
    135.     test    bl, 0x20        ; каков знак Y приращения?
    136.      je     @pozitivY
    137.     not     al              ; т.к. негативное перемещение инвертируем величину приращения
    138.     inc     ax              ; корреккция на 1
    139.     mul     dh              ; учтем масштабный коэффициент перемещения по Y
    140.     add     ax, bp          ; увеличим Y, т.к. эта ось "смотрит" вниз
    141.     cmp     ax, [iSCREEN.High]      ; нет ли теперь выхода за нижнюю границу экрана?
    142.      jc     @memNewY        ; если нет, то переход на сохранение нового значения Y
    143.     add     edi, 2          ; ничего не сохраняем, т.к. текущая координата Y мыши уже на нижнем краю экрана, просто корректировка указателя
    144.     jmp   @calcRET
    145.  
    146. @pozitivY:
    147.     mul     dh              ; учтем масштабный коэффициент перемещения по Y
    148.     xchg    ax, bp          ; развернули для удобства действий
    149.     sub     ax, bp          ; вычтем и получим новую координату Y
    150.      jnc    @memNewY        ; перебор за ноль ?
    151.     xor     ax, ax          ; это так, поэтому делаем Y = 0
    152. @memNewY:
    153.     mov     [edi], ax           ; сохранить новую координату в [_Y_Mouse]
    154.     add     edi, 2
    155.  
    156. @calcRET:
    157.  
    158.  
    159.  
    160. @q:
    161.     mov     ax, 0x20        ; EIO
    162.     out     0xA0, al
    163.     mov     dx, ax
    164.     out     dx, al
    165.     popad
    166.     pop     ds
    167.        IRET
    довесочек
    Код (Text):
    1. ALIGN  4
    2. SetLEDsKBD:
    3.     push    eax
    4.     mov     ax, 0x60ED
    5.     call    AddNewCmdKBC
    6.     pop     eax
    7.     and     al, 7
    8.     mov     ah, 0x60
    9. AddNewCmdKBC:
    10.     mov     edx, [iKBC.EndCmdKBC]   ; берем адрес головы строки команд
    11.     cmp     edx, iKBC.EndLineCmd-2  ; очередь заполнена до конца ?
    12.      jnc    @retAddNewCmdKBC
    13.     mov     [edx], ax           ; помещаем в очередь новую команду для выполнения
    14.     add     [iKBC.EndCmdKBC], 2     ; переместим указатель головы
    15.     or      [iTMR0.FlagTskTmr], FlagCmdKBC ; выставим флаг обработки строки соманд клавиатуры
    16. @retAddNewCmdKBC:
    17.        RET
    Курились следующие маны (подборка) doc.rar

    Непременно радостных Успехов! ;o)