Организация высокоуровневого консольного ввода-вывода
Ниже приведен пример пользовательского обработчика события – ввода комбинации CTRL + C или CTRL + Break. За основу взята предыдущая программа.
:prg05_12.asm – программа, демонстрирующая использование пользовательского обработчика события. .data Text_CTRL_C db "Нажаты CTRL + C" Len_Text_CTRL=$-Text_CTRL_C TextJREAK db "Нажаты CTRL + BREAK" Len_BREAK=$-Text_BREAK .code CTRLHandler proc arg @@dwCTRLType:DWORD uses ebx.edi .esi;эти регистры обязательно должны сохраняться :анализируем тип сигнала управления cmp @@dwCTRLType.CTRL_C_EVENT je h_CTRL_C_EVENT cmp (a@dwCTRLType.CTRL_BREAK_EVENT je h_CTRL_BREAK_EVENT jmp h_default h_CTRL_C_EVENT::при нажатии CTRL + C выводим сообщение: установим курсор call SetConsoleCursorPosition:вывести строку Text_CTRL_C call WriteConsoleA ; возвращаем признак обработки mov eax.l jmp exit_CTRLHandler h_CTRL_BREAK_EVENT: ;при нажатии CTRL + BREAK выводим сообщение: ;установим курсор call SetConsoleCursorPosition: вывести строку call WriteConsoleA ;возвращаем признак обработки mov eax.l jmp exit_CTRLHandler h_default: mov eax.Offffffffh;возвращаем остальное не обрабатываем exit_CTRLHandler: ret CTRLHandler endp start proc near;точка входа в программу: :работаем……… :получим стандартные дескрипторы ввода-вывода ;установим функцию-обработчик сигналов управления push TRUE push offset cs: CTRLHandler call SetConsoleCTRLHandler onp eax. 0 jz exit:если неуспех;введем строку в буфер TitleText установим курсор в позицию (2.6) call SetConsoleCursorPosition call ReadConsoleA :выведем введенную строку в заголовок окна консоли: push offset TitleText call SetConsoleTitleA :выведем строку в окно консоли с различных позиций и с разными цветами mov ecx.10:строку выведем 10 раз mov bl.10000001b начальные атрибуты ml: push ecx установим курсор в позицию call SetConsoleCursorPosition ;определим атрибуты выводимых символов – будем получать их циклически сдвигом регистра BL хоr еах.еах rol b1.1 mov al,b1 push eax push d0ut call SetConsoleTextAttribute.:вывести строку TitleText call WriteConsoleA cmp eax.0 jz exit;если неуспех pop ecx loop ml
Относительно этой программы можно сделать два замечания. Первое касается функции HandlerRoutine, которая в нашей программе называется CTRL Handler. Как упоминалось, эта функция является функцией обратного вызова. Ее вызов производится при возникновении определенных событий неявно – из системы Windows. По структуре и алгоритму работы она аналогична оконной функции, которую мы рассматривали в уроке 18 "Создание Windows-приложений на ассемблере" учебника. Поэтому за всеми подробностями отсылаем читателя к этому материалу. Второе замечание касается порядка отладки приложений, содержащих определяемые пользователем функции (процедуры) обратного вызова.
Первое, что нужно сделать в процессе пошагового выполнения программы в отладчике, – выяснить адрес процедуры обратного вызова. В программе выше это можно сделать, выяснив, какое значение будет помещено в стек при выполнении команд:
………. [установим функцию-обработчик сигналов управления push TRUE push offset cs: CTRL Handler call SetConsoleCTRLHandler cmp eax. 0 jz exit [если неуспех ………
После этого, сделав активным окно отладчика CPU (выбрав в меню команду View CPU), необходимо установить указатель мыши в окно с командами процессора и щелкнуть правой кнопкой мыши. В появившемся контекстном меню выберете пункт Goto…. В результате этих действий отладчик отобразит диалоговое окно, в которое необходимо внести адрес программы-обработчика CTRL Handler. В результате этого в верхней части окна команд отобразится первая команда процедуры CTRL Handler. Установите на нее курсор и нажмите клавишу F4.
Все, программа начнет выполняться по своему алгоритму. При нажатии пользователем управляющих комбинаций клавиш, допустимых функцией HandlerRoutine, управление будет передано этой функции, и вы сможете произвести ее отладку.