На этом шаге мы рассмотрим общие принципы создания консольных приложений.
Консольное приложение - приложение, выполняемое из коммандной строки, например из коммандной строки Far. Часто нет необходимости и времени для создания графического интерфейса, а программа должна что-то делать, например, обрабатывать большие объемы информации. И вот тут на помощь приходят консольные приложения. Ниже вы увидите, что консольные приложения очень компактны не только в откомпилированном виде, но и в текстовом варианте. Но главное, консольное приложение имеет такие же возможности обращаться к ресурсам Windows посредством API-функций, как и обычное графическое приложение.
Приведем параметры для создания консольных приложений:
ml /с /coff cons1.asm link /subsystem:console cons1.obj
tasm32 /ml cons1.asm tlink32 /ap consl.obj
Как и раньше, мы предполагаем, что библиотеки будут указываться при помощи директивы includelib. Ниже представлено простое консольное приложение для MASM и TASM соответственно. Для вывода текстовой информации используется функция API WriteConsoleA, параметры которой (слева направо) имеют следующий смысл:
Заметим, что буфер, где находится выводимый текст, не обязательно должен заканчиваться нулем, поскольку для данной функции указывается количество выводимых символов. Договоримся только не путать входные/выходные буферы консоли и буферы, которые мы создаем в программе, в том числе и для обмена с буферами консоли.
.386P ;Плоская модель памяти. .MODEL FLAT, STDCALL ;Константы. STD_OUTPUT_HANDLE equ -11 ;Прототипы внешних процедур. EXTERN GetStdHandle@4:NEAR EXTERN WriteConsoleA@20:NEAR EXTERN ExitProcess@4:NEAR ;Директивы компоновщику для подключения библиотек. includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ;Сегмент данных. _DATA SEGMENT DWORD PUBLIC USE32 'DATA' ;Строка в DOS-овской кодировке. STR1 DB "Консольное приложение",0 LENS DD ? ;Количество выведенных символов. RES DD ? _DATA ENDS ;Сегмент кода. _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ;Получить HANDLE вывода. PUSH STD_OUTPUT_HANDLE CALL GetStdHandle@4 ;Длина строки. PUSH OFFSET STR1 CALL LENSTR ;Вывести строку. PUSH OFFSET RES ;Резерв. PUSH OFFSET LENS ;Выведено символов. PUSH EBX ;Длина строки. PUSH OFFSET STR1 ;Адрес строки. PUSH EAX ;HANDLE вывода. CALL WriteConsoleA@20 PUSH 0 CALL ExitProcess@4 ;Строка - [EBP+08H]. ;Длина в ЕВХ LENSTR PROC PUSH EBP MOV EBP,ESP PUSH EAX ;---------------------- CLD MOV EDI,DWORD PTR [EBP+08H] MOV EBX,EDI MOV ECX,100 ;Ограничить длину строки. XOR AL,AL REPNE SCASB ;Найти символ 0. SUB EDI,EBX ;Длина строки, включая 0. MOV EBX,EDI DEC EBX ;---------------------- POP EAX POP EBP RET 4 LENSTR ENDP _TEXT ENDS END START
.386P ;Плоская модель памяти. .MODEL FLAT, STDCALL ;Константы. STD_OUTPUT_HANDLE equ -11 ;Прототипы внешних процедур. EXTERN GetStdHandle:NEAR EXTERN WriteConsoleA:NEAR EXTERN ExitProcess:NEAR ;Директивы компоновщику для подключения библиотек. includelib c:\tasm32\lib\import32.lib ;Сегмент данных. _DATA SEGMENT DWORD PUBLIC USE32 'DATA' ;Строка в DOS-овской кодировке. STR1 DB "Консольное приложение",0 LENS DD ? ;Количество выведенных символов. RES DD ? _DATA ENDS ;Сегмент кода. _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ;Получить HANDLE вывода. PUSH STD_OUTPUT_HANDLE CALL GetStdHandle ;Длина строки. PUSH OFFSET STR1 CALL LENSTR ;Вывести строку. PUSH OFFSET RES ;Резерв. PUSH OFFSET LENS ;Выведено символов. PUSH EBX ;Длина строки. PUSH OFFSET STR1 ;Адрес строки. PUSH EAX ;HANDLE вывода. CALL WriteConsoleA PUSH 0 CALL ExitProcess ;Строка - [EBP+08H]. ;Длина в ЕВХ LENSTR PROC PUSH EBP MOV EBP,ESP PUSH EAX ;---------------------- CLD MOV EDI,DWORD PTR [EBP+08H] MOV EBX,EDI MOV ECX,100 ;Ограничить длину строки. XOR AL,AL REPNE SCASB ;Найти символ 0. SUB EDI,EBX ;Длина строки, включая 0. MOV EBX,EDI DEC EBX ;---------------------- POP EAX POP EBP RET 4 LENSTR ENDP _TEXT ENDS END START
Надо сказать, что, поскольку информация выводится в консольном окне, кодировка всех строковых констант должна быть для DOS. В дальнейшем разъяснится вопрос, как осуществить перекодировку программным путем.
Прокомментируем теперь приведенные выше программы. При запуске их из командной строки, например из программы Far, в строку выводится сообщение "Консольное приложение". При запуске программы как Windows-приложения консольное окно появляется лишь на секунду. В чем тут дело? Дело в том, что консольные приложения могут создать свою консоль. В этом случае весь ввод-вывод будет производиться в эту консоль. Если же приложение консоль не создает, то здесь может возникнуть двоякая ситуация: либо наследуется консоль, в которой программа была запущена, либо Windows создает для приложения свою консоль.
На следующем шаге мы рассматрим вопросы, связанные с созданием консоли.