Консольные приложения Windows 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Консольные приложения 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 с.)