Sadda.ru Ironetcart Андроид Ассемблер MASM32 Linux Все статьи Table of Contents


 

API-функция ReadConsoleInput

  Макс Петров май 2013

      Функция определяется следующим образом:
      Function ReadConsoleInput Lib "kernel32" Alias DWORD "ReadConsoleInput" (DWORD hConsoleInput, DWORD lpBuffer, DWORD nLength, DWORD lpNumberOfEventsRead).
Функция содержится в библиотеке Windows kernel32, при успешном выполнении записывает в регистр EAX единицу, при ошибке - ноль. Функция не возвращает управление, пока не произойдет событие ввода.

      Передаваемые функции параметры:
      hConsoleInput - хэндл потока ввода консоли;
      lpBuffer - указатель на буфер, куда функция запишет событие (события) ввода;
      nLength - число записей о событиях ввода, которое мы хотим получить;
      lpNumberOfEventsRead - указатель на переменную, куда функция запишет число переданных событий.

      Самый интересный параметр - lpBuffer. Длина объявляемого в ассемблерной программе буфера зависит от числа событий ввода консоли, которые мы хотим получить. Для одного события требуется буфер не менее 20 байт. Больше можно ("хвост" буфера останется неиспользованным), но меньше нельзя - передаваемые функцией данные будут затирать следующие за буфером переменные, если же буфер в секции данных последний - произойдет генерация ошибки.

      Наиболее информативными являются следующие байты записи о событии во вводном потоке консоли:
      0 байт - событие клавиатуры "1", событие мыши "2";
      4 байт - клавиша нажата "1", клавиша отпущена "0", или горизонтальная координата мыши (от 0 до 79);
      6 байт - вертикальная координата мыши (от 0 до 255);
      8 байт - нажата левая кнопка мыши "1", правая "2", левая и правая "3", средняя 4", кнопки мыши отпущены "0";
      10 байт - код клавиши, или вращение колеса мыши от себя "120", вращение колеса мыши на себя "136";
      14 байт - символ в кодировке DOS, соответствующий нажатой клавише и состоянию управляющих клавиш;
      15 байт - латиница "0", кириллица "4";
      16 байт - состояние клавиш Caps Lock, Alt, Ctrl, Num Lock, Scroll Lock, Shift, вращение колеса мыши в любую сторону "4", двойной клик "2".

      Ниже программа, которая выводит в консоль первые 18 байтов (в десятичном формате) события консоли, пример использования функции ReadConsoleInput:

.386 .model flat, stdcall option casemap :none include C:\masm32\include\windows.inc include <\masm32\include\kernel32.inc> includelib <\masm32\lib\kernel32.lib> .data hConsoleInput DWORD ? ; переменные для хранения хэндлов ввода и вывода hConsoleOutput DWORD ? ; переменная для записи числа фактически NumberOfChars DWORD ? ; введенных или выведенных символов ; или числа переданных событий msg1310 byte 13, 10 ; перевод строки buffer1 byte 20 dup (35) ; буфер для приема сообщений о вводном ; событии консоли - не менее 20 байт buffer2 byte 79 dup (32) ; буфер, куда сообщение о событии ; перепишем с форматированием divider byte 10 ; делитель для машинной команды DIV .code start: invoke AllocConsole ; запрашиваем у Windows консоль invoke GetStdHandle, STD_INPUT_HANDLE ; получаем хэндл консоли для ввода mov hConsoleInput, EAX ; записываем хэндл в переменную invoke GetStdHandle, STD_OUTPUT_HANDLE ; получаем хэндл консоли для вывода mov hConsoleOutput, EAX ; записываем хэндл в переменную ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .while 1 ; НАЧАЛО БЕСКОНЕЧНОГО ЦИКЛА invoke ReadConsoleInputA, ; читаем событие ввода в консоль hConsoleInput, ; хэндл потока ввода addr buffer1, ; передаем функции адрес буфера 1, ; читаем одно событие addr NumberOfChars ; число переданных событий запишется сюда ; событие получено, далее его отформатируем - ; приведем значение байтов к десятичному виду, ; к символьному виду, добавим пробелы между ; значениями байтов, добавим возможность ; посмотреть байты 11 и 15, как символы mov EBX, 0 ; в EBX - номер байта буфера 1 (события) mov ECX, 0 ; в ECX - номер байта буфера 2 (форматирования) ; ----------------------------------------------- ; формируем выводной массив в буфере 2 .while EBX != 18 ; цикл продолжается, пока в EBX ; содержится число, не равное 18 ; переводим байты сообщения о событии в десятичное представление, ; для этого каждый байт (диапазон значений 0-255) расписываем ; на три байта, в которые помещаем значения порядков десятичного ; числа, например, байт со значением 255 распишется на 2, 5, 5, ; результат записываем в буфер buffer2 mov AX, 0 ; обнуляем AX mov AL, buffer1[EBX] ; копируем buffer1[EBX] в младший байт EAX DIV divider ; делим AX на байтовую переменную (10) mov buffer2[ECX + 2], AH ; копируем остаток от деления в buffer2[ECX + 2] mov AH, 0 ; обнуляем AH DIV divider ; делим AX на байтовую переменную (10) mov buffer2[ECX + 1], AH ; копируем остаток от деления в buffer2[ECX + 1] mov buffer2[ECX], AL ; копируем частное в buffer2[ECX] ; в предыдущем фрагменте байт buffer1[EBX] расписан ; в десятичном виде в три байта массива buffer2, ; теперь заменим содержимое байта buffer1[EBX], ; если оно меньше 32 (управляющие коды), пробелом - ; чтобы не вывести в виде расшифровки в скобках ; для байтов 10 и 14 в консоль непосредственно управляющий ; код (забой, табуляция, Enter и т.д. исказят картинку) .if buffer1[EBX] < 32 mov buffer1[EBX], 32 .endif ; если в обработке 10 байт, делаем ; в буфере 2 его символьную расшифровку .if EBX == 10 mov buffer2[ECX + 3], "(" ; пишем в буфер 2 символ "(" mov AL, buffer1[EBX] ; копируем buffer1[EBX] в AL mov buffer2[ECX + 4], AL ; копируем AL в buffer2[ECX + 4] mov buffer2[ECX + 5], ")" ; пишем в буфер 2 символ ")" inc ECX ; увеличиваем ECX на единицу inc ECX ; увеличиваем ECX на единицу inc ECX ; увеличиваем ECX на единицу .endif ; если в обработке 14 байт, делаем ; в буфере 2 его символьную расшифровку - ; аналогично предыдущему фрагменту .if EBX == 14 mov buffer2[ECX + 3], "(" mov AL, buffer1[EBX] mov buffer2[ECX + 4], AL mov buffer2[ECX + 5], ")" inc ECX inc ECX inc ECX .endif inc EBX ; увеличиваем индекс буфера 1 на единицу inc ECX ; увеличиваем индекс буфера 2 на единицу inc ECX ; увеличиваем индекс буфера 2 на единицу inc ECX ; увеличиваем индекс буфера 2 на единицу inc ECX ; увеличиваем индекс буфера 2 на единицу .endw ; ----------------------------------------------- ; далее заменяем числа в байтах ; буфера 2 их символьным представлением mov ECX, 0 .while ECX != 79 .if buffer2[ECX] >= 0 .if buffer2[ECX] <= 9 ADD buffer2[ECX], 48 .endif .endif inc ECX .endw ; ВЫВОДИМ 18 БАЙТОВ СОБЫТИЯ ВВОДА КОНСОЛИ invoke WriteConsoleA, hConsoleOutput, addr buffer2, 79, ADDR NumberOfChars, 0 invoke WriteConsoleA, hConsoleOutput, addr msg1310, 2, ADDR NumberOfChars, 0 .endw ; ВОЗВРАТ НА НАЧАЛО БЕСКОНЕЧНОГО ЦИКЛА ; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ invoke ExitProcess, 0 end start

      Выглядит вот так:

программа просмотра событий ввода консоли

     


Добавить комментарий

E-mail:
*


Контрольные цифры:



Ассемблер MASM32

      Простейшая программа на ассемблере (beeper)
      Переменные и типы данных ассемблера
      Регистры процессора IA32
      Консоль ввода-вывода
      API-функция CharToOem и строки ассемблера
      API-функция ReadConsoleInput
      API-функция PeekConsoleInput
      События консоли (таблица)
      Системы счисления, тэги ассемблера, перевод чисел
      Отрицательные числа
      Инкремент и декремент
      Деление (DIV, IDIV)
      VKDEBUG
      Макросы ассемблера
      Воспоминание об Альгамбре на системном динамике
      Командная строка
      Пузырьковая сортировка. Эстафета шариков
      Сортировка расческой
      Быстрая сортировка

     


© Max Petrov При использовании материалов ссылка на sadda.ru обязательна