Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Консольные приложения Windows
Консольные приложения представляют собой систему средств взаимодействия пользователя с компьютером, основанную на использовании текстового (буквенно-цифрового) режима дисплея или аналогичных (командная строка MS-DOS, Far). Консольные приложения очень компактны не только в откомпилированном виде, но и в текстовом варианте, и имеют такие же возможности обращаться к ресурсам Windows посредством API-функций, как и обычные графические приложение. Для работы с консольными приложениями Windows используются соответствующие функции Windows API. В программе на ассемблере записываются имена вызываемых функций как внешние, а сами функции расположены в системном каталоге Windows. Для обращения к ним используется подключаемый файл библиотеки (*.lib), в котором указывается, в каком системном.dll файле расположена вызываемая функция и файл описания прототипов функций (*.inc). Для подключения файла библиотеки используется директива includelib, для подключения файла прототипа – директива include: include С:\masm32\include\kernel32.inc includelib С:\masm32\lib\kernel32.lib Подключаемые библиотеки могут указываться в программе при помощи директивы includelib или при сборке приложения (команда link). Пример простейшего консольного приложения. .586 .MODEL flat, stdcall STD_OUTPUT_HANDLE EQU -11 ; константа Win API
include C:\masm32\include\kernel32.inc include C:\masm32\include\user32.inc include C:\masm32\include\msvcrt.inc includelib C:\masm32\lib\msvcrt.lib .data consoleOutHandle dd? ; дескриптор консоли вывода bytesWritten dd? ; количество байт(вспомогательная) message db "Привет всем!",13,10,0; текст (13 = \r, 10=\n 0=\0) h EQU $-message; ; длина текстовой строки (константа)
.code main PROC ; начало функции INVOKE GetStdHandle, STD_OUTPUT_HANDLE; Получить дескриптор консоли ввода mov consoleOutHandle,eax ; поместить его в EAX
INVOKE CharToOem,offset message,offset message; перекодировка сообщения
mov eax, h INVOKE WriteConsole, ; функция вывода в консоль consoleOutHandle, ; дескриптор консоли offset message, ; указатель строки eax, ; длина строки offset bytesWritten, ; количество выведенных байт 0 ; возвращается функцией
INVOKE crt__getch INVOKE ExitProcess,0 ; Окончание программы main ENDP ; окончание процедуры (функции) END main ; окончание модуля
Функция получения дескриптора стандартного устройства ввода, вывода или ошибки в зависимости от переданного константного параметра: HANDLE WINAPI GetStdHandle(__in DWORD nStdHandle); nStdHandle может принимать значения STD_INPUT_HANDLE = -10 устройство ввода STD_OUTPUT_HANDLE = -11 устройство вывода STD_ERROR_HANDLE = -12 ошибка Функция перекодировки русского текста, введенного в Win-кодовой странице, в код, читаемый в консоли (DOS-кодировку). Возвращаемое значение 1 в случае успешной перекодировки. BOOL CharToOem(LPCTSTR lpszSrc, LPSTR lpszDst) lpszSrc – указатель на строку-источник; lpszDst – указатель на строку-приемник; Функция вывода текстовой информации в консоль. BOOL WINAPI WriteConsole( __in HANDLE hConsoleOutput, __in const VOID* lpBuffer, __in DWORD nNumberOfCharsToWrite, __out LPDWORD lpNumberOfCharsWritten, __reserved LPVOID lpReserved); hConsoleOutput – дескриптор буфера вывода консоли, который может быть получен при помощи функции GetStdHandle. lpBuffer – указатель на буфер, где находится выводимый текст. nNumberOfCharsToWrite – количество выводимых символов. lpNumberOfCharsWritten – указывает на переменную DD, куда будет помещено количество действительно выведенных символов. lpReserved – резервный параметр, должен быть равен 0. Буфер, где находится выводимый текст, не обязательно должен заканчиваться нулем, поскольку для данной функции указывается количество выводимых символов. Функция завершения Windows-приложения. VOID WINAPI ExitProcess(__in UINT uExitCode); параметр uExitCode – код завершения. Для трансляции консольного приложения из командной строки используются следующие команды ml /с /coff cons1.asm link /subsystem:console cons1.obj При этом необходимо объявить все вызываемые API-функции как внешние с помощью директивы EXTERN. Трансляция из Visual Studio осуществляется аналогично диалоговому приложению, но необходимо указать платформу subsystem:console либо при создании проекта (тип Win32 Console Application), либо указать в уже существующем проекте в окне свойств. Основные динамические библиотеки kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib подключаются в командной строке редактора связей link.exe в Visual Studio, поэтому отсутствие директив типа includelib С:\masm32\lib\kernel32.lib не будет ошибкой. Библиотеки kernel32.lib, user32.lib подключаются линковщиком по умолчанию, поэтому нет необходимости подключать их директивой includelib.
Консольные приложения могут создать свою консоль. В этом случае весь ввод-вывод будет производиться в эту консоль. Если приложение консоль не создает, то здесь может возникнуть двоякая ситуация: либо наследуется консоль, в которой программа была запущена (например, консоль Fara), либо Windows создает для приложения свою консоль. Для того чтобы создать свою консоль, используется функция BOOL WINAPI AllocConsole(void); По завершении программы все выделенные консоли автоматически освобождаются. Однако это можно сделать и принудительно, используя функцию BOOL WINAPI FreeConsole(void);
Дополнительные функции для работы с консолью
Функция чтения строки из буфера консоли BOOL WINAPI ReadConsole( __in HANDLE hConsoleInput, __out LPVOID lpBuffer, __in DWORD nNumberOfCharsToRead, __out LPDWORD lpNumberOfCharsRead, __in_opt LPVOID pInputControl); hConsoleInput – дексриптор буфера ввода консоли, полученного функцией GetStdHandle. lpBuffer – указатель на буфер, куда помещается вводимый текст. nNumberOfCharsToRead – длина буфера ввода. lpNumberOfCharsRead– указатель на переменную DD (32 бит), куда будет помещено количество действительно введенных символов. pInputControl – резервный параметр, должен быть равен нулю. Функция опредления размеров окна консоли BOOL WINAPI SetConsoleScreenBufferSize( __in HANDLE hConsoleOutput, __in COORD dwSize); hConsoleOutput – дексриптор буфера вывода консоли; dwSize – структура координат, задающая размер окна консоли: COORD STRUC X DW? Y DW? COORD ENDS Функция установки позиции курсора в окне консоли BOOL WINAPI SetConsoleCursorPosition( __in HANDLE hConsoleOutput, __in COORD dwCursorPosition); hConsoleOutput– дексриптор буфера выходной консоли; dwCursorPosition– структура координат COORD, определяющая позицию курсора. Функция определения заголовка окна консоли BOOL WINAPI SetConsoleTitle(__in LPCTSTR lpConsoleTitle); lpConsoleTitle — указатель на строку имени консоли, заканчивающуюся нуль-символом. Функция определения атрибутов вводимых символов в окне консоли BOOL WINAPI SetConsoleTextAttribute( __in HANDLE hConsoleOutput, __in WORD wAttributes); hConsoleOutput – дексриптор буфера вывода консоли; wAttributes – цвет букв и фона, получаемый путем комбинации констант FOREGROUND_BLUE equ 1h;синий FOREGROUND_GREEN equ 2h;зеленый FOREGROUND_RED equ 4h;красный FOREGROUND_INTENSITY equ 8h;интенсивный BACKGROUND_BLUE equ 10h;синий фон букв BACKGROUND_GREEN equ 20h;зеленый фон букв BACKGROUND_RED equ 40h;красный фон букв BACKGROUND_INTENSITY equ 80h;интенсивный фон букв Функция, задающая цвет фона консоли (путем закрашивания фона отдельных символов) BOOL WINAPI FillConsoleOutputAttribute( __in HANDLE hConsoleOutput, __in WORD wAttribute, __in DWORD nLength, __in COORD dwWriteCoord, __out LPDWORD lpNumberOfAttrsWritten); hConsoleOutput – дексриптор буфера вывода консоли; wAttribute – атрибут цвета фона символа в консоли; nLength – количество ячеек символов, фон которых устанавливается заданным цветом; dwWriteCoord – координаты первой закрашиваемой ячейки; lpNumberOfAttrsWritten – указатель на 4-байтный идентификатор, в который записывается количество реально закрашенных ячеек. Функция, получающая информацию о клавиатуре и мыши в консольном режиме: BOOL WINAPI ReadConsoleInput( __in HANDLE hConsoleInput, __out PINPUT_RECORD lpBuffer, __in DWORD nLength, __out LPDWORD lpNumberOfEventsRead); hConsoleInput – дескриптор входного буфера консоли; lpBuffer – указатель на структуру (или массив структур) PINPUT_RECORD, в которой содержится информация о событиях, происшедших с консолью; nLength – количество получаемых информационных записей (структур);
lpNumberOfEventsRead – указатель на двойное слово, содержащее количество реально полученных записей. Структура PINPUT_RECORD используется для получения события, происшедшего в консоли. Всего системой зарезервировано пять типов событий: KEY_EV equ 1h ; клавиатурное событие MOUSE_EV equ 2h ; событие с мышью WINDOW_BUFFER_SIZE_EV equ 4h ; изменился размер окна MENU_EV equ 8h ; зарезервировано FOCUS_EV equ 10h ; зарезервировано Остальные байты структуры зависят от происшедшего события. Событие KEY_EVENT KEY_EVENT_RECORD STRUCT bKeyDown DD?;При нажатии клавиши значение поля больше нуля wRepeatCount DW?;Количество повторов при удержании клавиши wVirtualKeyCode DW?;Виртуальный код клавиши wVirtualScanCode DW?;Скан-код клавиши UNION UnicodeChar DW?;код символа в формате Unicode ;для функции (ReadConsoleInputW) AsciiChar DB?;код символа в формате ASCII ENDS ;для функции (ReadConsoleInputA) dwControlKeyState DD?;Содержится состояния управляющих клавиш. ;Может являться суммой следующих констант: ; RIGHT_ALT_PRESSED equ 1h ; LEFT_ALT_PRESSED equ 2h ; RIGHT_CTRL_PRESSED equ 4h ; LEFT_CTRL_PRESSED equ 8h ; SHIFT_PRESSED equ 10h ; NUMLOCK_ON equ 20h ; SCROLLLOCK_ON equ 40h ; CAPSLOCK_ON equ 80h ; ENHANCED_KEY equ 100h KEY_EVENT_RECORD ENDS Событие MOUSE_EVENT MOUSE_EVENT_RECORD STRUCT dwMousePosition COORD <>;координаты курсора мыши dwButtonState DD? ; состояние кнопок мыши. ;первый бит - левая кнопка, ;второй бит - правая кнопка, ;третий бит - средняя кнопка. ;Бит установлен - кнопка нажата. dwControlKeyState DD? ; Состояние управляющих клавиш dwEventFlags DD? ; Может содержать значения: ; MOUSE_MOVED equ 1h; было движение мыши ; DOUBLE_CLICK equ 2h; был двойной щелчок MOUSE_EVENT_RECORD ENDS
Событие WINDOW_BUFFER_SIZE_EVENT WINDOW_BUFFER_SIZE_RECORD STRUCT dwSize COORD <>; новый размер консольного окна WINDOW_BUFFER_SIZE_RECORD ENDS
События MENU_EVENT_RECORD и FOCUS_EVENT_RECORD зарезервированы. MENU_EVENT_RECORD STRUCT dwCommandId DD? MENU_EVENT_RECORD ENDS
FOCUS_EVENT_RECORD STRUCT bSetFocus DD? FOCUS_EVENT_RECORD ENDS
Структура, объединяющая все типы событий: INPUT_RECORD STRUCT EventType DW? DW? MY UNION KeyEvent KEY_EVENT_RECORD <> MouseEvent MOUSE_EVENT_RECORD <> WindowBufferSizeEvent WINDOW_BUFFER_SIZE_RECORD <> MenuEvent MENU_EVENT_RECORD <> FocusEvent FOCUS_EVENT_RECORD <> MY ENDS INPUT_RECORD ENDS В данном случае структуры всех событий: KeyEvent, MouseEvent, WindowBufferSizeEvent, MenuEvent, FocusEvent будут находиться в одной и той же области памяти размером 16 байт (по максимальной длине структуры KeyEvent, MouseEvent). Рассмотрим пример консольного приложения: посчитать количество символов в строке. Программа состоит из двух файлов. Файл console.inc содержит основные конструкции и константы Windows, необходимые при написании программы, а также основные функции. Файл mmm.asm содержит текст программы.
; файл console.inc include c:\masm32\include\user32.inc include c:\masm32\include\kernel32.inc
; константы дескрипторов буфера STD_INPUT_HANDLE equ -10 STD_OUTPUT_HANDLE equ -11 STD_ERROR_HANDLE equ -12
; структура координат COORD STRUC X DW? Y DW? COORD ENDS
;Цвет окна консоли FOREGROUND_BLUE equ 1h; синий цвет букв FOREGROUND_GREEN equ 2h; зеленый цвет букв FOREGROUND_RED equ 4h; красный цвет букв FOREGROUND_INTENSITY equ 8h; повышенная интенсивность BACKGROUND_BLUE equ 10h; синий свет фона BACKGROUND_GREEN equ 20h; зеленый цвет фона BACKGROUND_RED equ 40h; красный цвет фона BACKGROUND_INTENSITY equ 80h; повышенная интенсивность
; тип события KEY_EV equ 1h ; клавиатурное событие MOUSE_EV equ 2h ; событие с мышью WINDOW_BUFFER_SIZE_EV equ 4h ; изменился размер окна MENU_EV equ 8h ; зарезервировано FOCUS_EV equ 10h ; зарезервировано
; константы - состояния клавиатуры RIGHT_ALT_PRESSED equ 1h LEFT_ALT_PRESSED equ 2h RIGHT_CTRL_PRESSED equ 4h LEFT_CTRL_PRESSED equ 8h SHIFT_PRESSED equ 10h NUMLOCK_ON equ 20h SCROLLLOCK_ON equ 40h CAPSLOCK_ON equ 80h ENHANCED_KEY equ 100h
;события мыши MOUSE_MOVED equ 1h; было движение мыши DOUBLE_CLICK equ 2h; был двойной щелчок
;описание событий структуры PINPUT_RECORD ;событие мыши MOUSE_EVENT_RECORD STRUCT dwMousePosition COORD <> dwButtonState DWORD? dwControlKeyState DWORD? dwEventFlags DWORD? MOUSE_EVENT_RECORD ENDS
;событие клавиатуры KEY_EVENT_RECORD STRUCT bKeyDown DD? wRepeatCount DW? wVirtualKeyCode DW? wVirtualScanCode DW? UNION UnicodeChar DW? AsciiChar DB? ENDS dwControlKeyState DD? KEY_EVENT_RECORD ENDS
;изменение размера окна консоли WINDOW_BUFFER_SIZE_RECORD STRUCT dwSize COORD <> WINDOW_BUFFER_SIZE_RECORD ENDS
MENU_EVENT_RECORD STRUCT dwCommandId DWORD? MENU_EVENT_RECORD ENDS
FOCUS_EVENT_RECORD STRUCT bSetFocus DWORD? FOCUS_EVENT_RECORD ENDS
;Структура PINPUT_RECORD INPUT_RECORD STRUCT EventType DW? DW? UNION KeyEvent KEY_EVENT_RECORD <> MouseEvent MOUSE_EVENT_RECORD <> WindowBufferSizeEvent WINDOW_BUFFER_SIZE_RECORD <> MenuEvent MENU_EVENT_RECORD <> FocusEvent FOCUS_EVENT_RECORD <> ENDS INPUT_RECORD ENDS
; Секция данных содержит временные переменные .data @CO DD? @numBytes DD? KeyEvent INPUT_RECORD <> @SYMBOL DB? .code ;------------------------------------------------------------------- ; Функция считывание символа в консоли ; consoleInHandle - дескриптор буфера консоли ввода ; consoleOutHandle - дескриптор буфера консоли вывода ; Display - управление отображением символа: ; 0 - символ отображается ; 1 - символ не отображается ; функция возвращает считанный символ в регистре al ReadSymbol proc consoleInHandle:DWORD, consoleOutHandle:DWORD, Display:DWORD @L1: INVOKE ReadConsoleInputA, consoleInHandle, offset KeyEvent, 1, offset @CO CMP KeyEvent.EventType,KEY_EV JNE @L1
; сохранение введенного символа MOV AL, KeyEvent.KeyEvent.AsciiChar MOV @SYMBOL, AL
CMP Display,0 JNE @L2
;вывод символа INVOKE WriteConsoleA, consoleOutHandle, OFFSET @SYMBOL, 1, OFFSET @numBytes, 0 ; Считывание события клавиатуры отпускания клавиши @L2: INVOKE ReadConsoleInputA, consoleInHandle, offset KeyEvent, 1, offset @CO CMP KeyEvent.EventType,KEY_EV JNE @L2
mov eax,0 mov al, @SYMBOL ret ReadSymbol endp ;------------------------------------------------------------------- ;Представление целого числа в текстовой форме ; Number - целое число ; Str1 - указатель на строку, в которую будет помещено представление числа
; функция возвращает длину строки символов в регистре EAX IntToStr proc Number:DWORD, Str1:DWORD MOV EAX, Number MOV EDI,Str1 MOV ECX, 0 CMP EAX,0 JGE @I1 MOV DL, '-' MOV [EDI],DL INC EDI NOT EAX INC EAX @I1: MOV EBX, 10 MOV EDX, 0 IDIV EBX PUSH EDX INC ECX CMP EAX,0 JG @I1 ; MOV EBX,ECX @I2: POP EDX ADD DL, 30h MOV [EDI],DL INC EDI LOOP @I2 MOV DL,0 MOV [EDI], DL INC EDI MOV EAX, EDI SUB EAX, Str1 ret IntToStr endp ;------------------------------------------------------------------- ;Определение длины строки ;Str1 - указатель на строку ; функция возвращает длину строки символов в регистре EAX LENSTR PROC Str1:DWORD CLD CLD MOV EDI, Str1 MOV EBX,EDI MOV ECX,100; ограничить длину строки MOV EAX, 0 REPNE SCASB; найти символ 0 SUB EDI, EBX; длина строки, включая 0 MOV EAX,EDI DEC EAX RET LENSTR ENDP ;------------------------------------------------------------------- ; Вывод строки в окно консоли ; StrPtr - указатель на выводимую строку, оканчивающуюся 0 ; consoleOutHandle - дескриптор буфера консоли вывода PrintStr proc StrPtr:DWORD, Handle:DWORD INVOKE CharToOem, StrPtr, StrPtr INVOKE LENSTR, StrPtr; определение длины строки INVOKE WriteConsole, Handle, StrPtr, eax, OFFSET @numBytes, 0 ret PrintStr endp
; файл mmm.asm .586 .MODEL FLAT, stdcall include console.inc .DATA consoleOutHandle DD?; дескриптор выходного буфера consoleInHandle DD?; дескриптор входного буфера COUNT DD 0 ; счетчик количество символов numBytes DD? TITL DB "Подсчет количества символов в строке",0 IN_STR DB "Введите строку: ",0 IN_SYM DB "Введите символ: ",0 BUF DB 200 dup (?); для ввода строки Len DD? ; длина введенной строки Yes DB 13,10,"Количество символов: ",0 No DB 13,10,"Символ не найден.",0 SymCount DB 10 dup(?); строка с количеством символов CRD COORD <?> ; структура координат .CODE START proc ; образовать консоль, вначале освободить уже существующую INVOKE FreeConsole INVOKE AllocConsole ; получить дескрипторы INVOKE GetStdHandle, STD_INPUT_HANDLE MOV consoleInHandle,EAX INVOKE GetStdHandle, STD_OUTPUT_HANDLE MOV consoleOutHandle,EAX ; задать заголовок окна консоли INVOKE CharToOem, OFFSET TITL, OFFSET TITL INVOKE SetConsoleTitle, OFFSET TITL ; задать размер окна консоли MOV CRD.X, 80 MOV CRD.Y, 25 mov eax, CRD INVOKE SetConsoleScreenBufferSize, consoleOutHandle, EAX ; задать цвет окна консоли INVOKE FillConsoleOutputAttribute, consoleOutHandle, BACKGROUND_BLUE + BACKGROUND_GREEN, 2000, 0, offset numBytes ; установить позицию курсора MOV CRD.X,0 MOV CRD.Y,2 mov eax, CRD INVOKE SetConsoleCursorPosition, consoleOutHandle, EAX ; задать цветовые атрибуты выводимого текста INVOKE SetConsoleTextAttribute, consoleOutHandle, FOREGROUND_BLUE + \ BACKGROUND_BLUE + BACKGROUND_GREEN
;Вывод сообщения Введите строку: INVOKE PrintStr, offset IN_STR, consoleOutHandle ;Ввод строки INVOKE ReadConsole, consoleInHandle, OFFSET BUF, 200, OFFSET numBytes, 0 ; Сохранить длину введенной строки MOV EAX, numBytes MOV Len, EAX ;Вывод сообщения Введите символ: INVOKE PrintStr, offset IN_SYM, consoleOutHandle ;Считывание символа INVOKE ReadSymbol, consoleInHandle, consoleOutHandle, 0 ; поиск символа в строке ; символ содержится в регистре AL CLD ; поиск символа с начала строки DF=0 LEA EDI, BUF; MOV ECX, Len;количество повторений равно длине строки FIND: repne SCASB JNE FAILED; просмотр строки завершен INC COUNT JMP FIND ; символ не найден FAILED: CMP COUNT, 0 JNE FOUND; количество символов не 0 – идем на FOUND INVOKE CharToOem, OFFSET No, OFFSET No; таких символов нет INVOKE PrintStr, offset No, consoleOutHandle JMP EXIT ; символ найден FOUND: INVOKE PrintStr, offset Yes, consoleOutHandle INVOKE IntToStr, COUNT, offset SymCount INVOKE PrintStr, offset SymCount, consoleOutHandle EXIT: INVOKE ReadSymbol, consoleInHandle, consoleOutHandle, 1 INVOKE ExitProcess,0 RET START ENDP END START
|
|||||||||
Последнее изменение этой страницы: 2020-12-09; просмотров: 352; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.220.160.216 (0.239 с.) |