assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 101
Текст из файла (страница 101)
При запуске консольного приложения список функций-обработчиков содержит только заданную по умолчанию функцию, котораявызывает функцию ExitProcess. Консольный процесс может добавлять или удалять дополнительные функции-обработчики, вызывая функцию SetConsoleCtrlHandler:BOOL S e t C o n s o l e C t r l H a n d l e r ( P H A N D L E R _ R O U T I N E H a n d l e r R o u t i n e , BOOL A d d ) ;Данная функция имеет два параметра:it HandlerRoutine — указатель на определенную приложением функцию HandlerRoutine, которая должна быть добавлена или удалена;II Add — логическое значение:P i — функция должна быть добавлена;D O — функцию необходимо удалить.Функция HandlerRoutine — это определенная приложением функция обратноговызова. Консольный процесс использует эту функцию, чтобы обработать нажатияклавиш управления.
На самом деле HandlerRoutine — идентификатор-заполнительдля определенного приложением имени функции:BOOL W I N A P I H a n d l e r R o u t i n e ( D W O R D d w C t r l T y p e ) ;Параметр DwCtrlType определяет тип сигнала управления, получаемого обработчиком. Этот параметр может принимать одно из следующих значений:К CTRL_C_EVENT = 0 — сигнал, имитирующий нажатие клавиш Ctrl+C, может бытьполучен из двух источников: с клавиатуры или от функции GenerateConsoleCtrlEvent;9 CTRL_BREAK_EVENT = 1 — сигнал, имитирующий нажатие клавиш Ctrl+Break, может быть получен из двух источников: с клавиатуры или от функции GenerateConsoleCtrlEvent;il CTRL_CLOSE_EVENT = 2 — сигнал, который система посылает всем процессам, подключенным к данному консольному приложению, когда пользователь его закрывает (выбирая пункт Close в системном меню окна консоли или щелкая накнопке завершения задачи в диалоговом окне Менеджера задач);ii CTRL_LOGOFF_EVENT = 5 — сигнал, который посылается всем консольным процессам, когда пользователь завершает работу в системе (этот сигнал не указывает,какой именно пользователь завершает работу);ii CTRL_SHUTDOWN_EVENT = б — сигнал, который система посылает всем консольным процессам при подготовке к выключению машины.Программирование консольных Windows-приложений443Функция HandlerRoutine должна возвратить логическое значение: 1 — если онаобрабатывает конкретный сигнал управления; 0 — для обработки полученного события будет использоваться другая функция-обработчик HandlerRoutine из спискафункций-обработчиков этого процесса (то есть включенная в этот список раньшеданной функции).Как уже было упомянуто, каждый консольный процесс может определить несколько функций HandlerRoutine, которые связываются в цепочку.
Первоначальноэтот список содержит только заданную по умолчанию функцию-обработчик, вызывающую функцию ExitProcess, что в результате приводит к завершению текущего консольного приложения. Консольный процесс добавляет или удаляет дополнительные функции-обработчики, вызывая функцию SetConsoleCtrlHandler, котораяне затрагивает список функций-обработчиков других процессов. Когда консольный процесс принимает любой из сигналов управления (см. выше), то вызываетсяпоследняя зарегистрированная функция-обработчик, если она не возвращает 1, тоуправление передается следующему (предыдущему) зарегистрированному обработчику и так продолжается до тех пор, пока один из обработчиков не возвратит 1.Если ни один из обработчиков этого не сделал, то вызывается обработчик, заданный по умолчанию.Установка обработчиков для сигналов CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENTи CTRL_SHUTDOWN_EVENT дает процессу возможность выполнить специфичные длянего действия по корректному завершению приложения.
Пользовательская функция HandlerRoutine может быть вызвана для того, чтобы выполнить следующие действия:1вызвать функцию ExitProcess для завершения процесса;возвратить 0 (ложь) — это означает, что завершение приложения должен выполнить обработчик, заданный по умолчанию;возвратить 1 — в этом случае никакие другие функции-обработчики не вызываются, и система отображает модальное окно диалога с запросом о необходимости завершения процесса.В последнем случае система также отображает окно диалога, если процесс неотвечает определенное время (5 секунд для CTRL_CLOSE_EVENT и 20 секунд дляCTRL_LOGOFF_EVENT и CTRL_SHUTDOWN_EVENT).
Процесс может использовать функцию SetProcessShutdownParameters, чтобы запретить системе отображать окно диалога. В этом случае система просто заканчивает процесс, когда HandlerRoutine возвращает истину или когда истекает определенный период времени.В листинге 16.16 приведен пример пользовательского обработчика события —ввода комбинации Ctrl+C или Ctrl+Break. За основу взята предыдущая программа.Листинг 16.16. Фрагменты приложения prg16_7.asm;prg!6_7.asm - программа, демонстрирующаяпользовательский обработчик события..datafext_CTRL_C db "Нажаты CTRL+C"Len_Text_CTRL=$-Text_CTRL_CTextBREAKdb"Нажаты CTRL+BREAK"продолжение iy444Глава 16.
Создание Windows-приложений на ассемблереЛистинг 16.16 (продолжение)Len_BREAK=$-Text_BREAK. codeCtrlHandler procarg @@dwCtrlType:DWORDuses ebx.edi, esi;эти регистры обязательно должны сохраняться;анализируем тип сигнала управленияcmp @@dwCtrlType,CTRL_C_EVENTje h_CTRL_C_EVENTcmp @@dwCtrlType,CTRL_BREAK_EVENTje h_CTRL_BREAK_EVENTjmp h_defaulth_CTRL__C_EVENT:;при нажатии CTRL+C выводим сообщение:установим курсорcallSetConsoleCursorPositionвывести строку Text_CTRL_CcallWriteConsoleAвозвращаем признак обработкиmov eax, 1jmp exit_CtrlHandlerh_CTRL_BREAK_EVENT:установим курсорcall;при нажатии CTRL+BREAK выводим сообщение:SetConsoleCursorPositionвывести строкуcallWriteConsoleAвозвращаем признак обработкиmov eax.ljmp exit_CtrlHandlerh_default: mov eax ,0ffffffffhвозвращаем -1;все остальное не обрабатываемexit_CtrlHandler:retCtrlHandler endpstartproc near;точка входа в программу:;работаем .
. .;получим стандартные дескрипторы ввода-вывода;установим функцию-обработчик сигналов управленияpushTRUEpushoffset cs: CtrlHandlercallSetConsoleCtrlHandlercmpeax, 0jzexit;если неуспехвведем строку в буфер TitleTextустановим курсор в позицию (2,6)callSetConsoleCursorPositioncallReadConsoleAвыведем введенную строку в заголовок окна консоли:pushoffset TitleTextcallSetConsoleTitleAвыведем строку в окно консоли с различных позиций и с разными цветамиmovecx.lQ;строку выведем 10 разmovbl,10000001b;начальные атрибутыПрограммирование консольных Windows-приложений445ml: pushecx;установим курсор в позициюcallSetConsoleCursorPosition;определим атрибуты выводимых символов:;будем получать их циклически - сдвигом регистра BLхог еах.еахrol Ы,1mov al.blpusheaxpushdOutcallSetConsoleTextAttributeвывести строку TitleTextcallWriteConsoleAcmp eax.Ojz exitpop ecxloopml;если неуспехОтносительно этой программы можно сделать два замечания.
Первое касаетсяфункции HandlerRoutine, которая в нашей программе называется CtrlHandler. Какупоминалось, эта функция является функцией обратного вызова. Она вызываетсяпри возникновении определенных событий неявно — из системы Windows. Поструктуре и алгоритму работы она аналогична оконной функции, которую мы рассматривали ранее (см. раздел «Каркасное Windows-приложение на C/C++»). Поэтому за всеми подробностями отсылаем читателя к этому материалу.
Второе замечание касается порядка отладки приложений, содержащих определяемыепользователем функции (процедуры) обратного вызова. Первое, что нужно сделать в процессе пошагового выполнения программы в отладчике, — выяснить адрес процедуры обратного вызова. В программе из листинга 16.16 это можно сделать, выяснив, какое значение будет помещено в стек при выполнении команд:;установим функцию-обработчик сигналов управленияpushTRUEpushoffset cs: CtrlHandlercallSetConsoleCtrlHandlercmpeax, 0jzexit;если неуспехПосле этого, сделав активным окно CPU отладчика (выбрав в меню командуView > CPU), необходимо установить указатель мыши в окно с командами процессора и щелкнуть правой кнопкой мыши.
В появившемся контекстном меню выберите пункт Goto. В результате этих действий отладчик отобразит окно диалога,в которое необходимо внести адрес программы-обработчика CtrlHandler. После этогов верхней части окна команд отобразится первая команда процедуры CtrlHandler.Установите на нее курсор и нажмите клавишу F4. Программа начнет выполнятьсяпо своему алгоритму. При нажатии пользователем управляющих комбинаций клавиш, допустимых функцией HandlerRoutine, управление будет передано этой функции, и вы сможете произвести ее отладку.Низкий уровень консольного ввода-вывода по сравнению с высоким обладаетболее широкими и гибкими возможностями.
Низкоуровневые функции консоль-446Глава 16. Создание Windows-приложений на ассемблереного ввода-вывода обеспечивают прямой доступ к входному и экранным буферамконсоли, предоставляя приложению доступ к событиям мыши и клавиатуры, а также к информации об изменении размеров окна консоли. Функции низкоуровневого ввода-вывода позволяют приложению иметь доступ по чтению-записик указанному числу последовательных символьных ячеек в экранном буфереили к прямоугольному блоку символьных ячеек в указанной позиции экранного буфера.Итогия Разработка Windows-приложения на языке ассемблера — вполне реальное и вряде случаев оправданное дело. Однако несмотря на имеющиеся в TASMи MASM средства, для создания полноценного Windows-приложения требуются дополнительные программные и информационные ресурсы, предоставляемые пакетами языков высокого уровня.