| ||
What are console applications? They are indispensable tools for those who love to work with command line. The most beloved and famous console application is Far Manager (Far.exe). When working with such applications, at first glance it might seem that you are working with an MS-DOS program. However, the reason behind the popularity of console applications isn't any special love for the text mode. Quite often, there is no special need in graphical user interface; moreover, you as the programmer often have no time to implement it. At the same time, your program must do something useful, for example, process large volumes of information. In this situation, console applications are helpful. Later, you'll see that console applications are compact, not only in the compiled form but also in the text variant. The most important point is that a console application has the same possibilities of accessing Windows resources, by calling API functions, as any normal Graphic User Interface (GUI) application.
In this book, I use MASM32 6.14 and TASM32 5.0 for assembling and linking console applications. Here, everything is quite simple.
For MASM:
ml /c /coff consl.asm link /subsystem:console consl.obj
For TASM32:
TASM32 /ml consl.asm tlink32 /ap consl.exe
As before, I specify the libraries using the INCLUDELIB directive. Listings 8.1 and 8.2 present variants of a simple console application for MASM and TASM, respectively.
For text output, I'll use the WriteConsoleA API function, which receives the following parameters (counted from left to right):
First parameterDescriptor of the output buffer of the console, which can be obtained using the GetStdhandle function
Second parameterPointer to the buffer that contains the text for output
Third parameterNumber of characters for output
Fourth parameterPointer to the DWORD variable that will store the number of characters actually displayed on the console
Fifth parameterReserved; should be zero
Note that the buffer that contains the text for output mustn't necessarily be terminated with zero, because this function accepts the number of characters for output as one of its parameters. It is only necessary to agree that you won't confuse the input or output buffers of the console and the buffers created within the program, including the ones created especially for exchanging data with console buffers.
.586P ; Flat memory model .MODEL FLAT, stdcall ; Constants STD_OUTPUT_HANDLE equ -11 ; Prototypes of external procedures EXTERN GetStdHandle@4:NEAR EXTERN WriteConsoleA@20:NEAR EXTERN ExitProcess@4:NEAR ; Directives for the linker to link libraries includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib ;------------------------------------------- ; Data segment _DATA SEGMENT ; DQS-encoded string STR1 DB "Console application", 0 LENS DD ? ; Number of output characters RES DD ? _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get the output handle PUSH STD_OUTPUT_HANDLE CALL GetStdHandle@4 ; String length PUSH OFFSET STR1 CALL LENSTR ; Output the string PUSH OFFSET RES ; Reserved PUSH OFFSET LENS ; Symbols displayed PUSH EBX ; String length PUSH OFFSET STR1 ; String address PUSH EAX ; Output handle CALL WriteConsoleA@20 PUSH 0 CALL ExitProcess@4 ; String - [EBP+08H] ; Length in EBX LENSTR PROC PUSH EBP MOV EBP, ESP PUSH EAX ;------------- CLD MOV EDI, DWORD PTR [EBP+08H] MOV EBX, EDI MOV ECX, 100 ; Limit the string length XOR AL, AL REPNE SCASB ; Find the 0 character SUB EDI, EBX ; String length including 0 MOV EBX, EDI DEC EBX ;------------------------ POP EAX POP EBP RET 4 LENSTR ENDP _TEXT ENDS END START
.586P ;Flat memory model ;MODEL FLAT, stdcall ; Constants STD_OUTPUT_HANDLE equ -11 ; Prototypes of external procedures EXTERN GetStdHandle:NEAR EXTERN WriteConsoleA:NEAR EXTERN ExitProcess:NEAR ; Directives for the linker to link libraries includelib c:\tasm32\lib\import32.lib ;-------------------- ; Data segment _DATA SEGMENT ; DOS-encoded string STR1 DB "Console application", 0 LENS DD ? ; Number of displayed characters RES DD ? _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get the output handle PUSH STD_OUTPUT_HANDLE CALL GetStdHandle ; String length PUSH OFFSET STR1 CALL LENSTR ; Display the string PUSH OFFSET RES ; Reserved PUSH OFFSET LENS ; Characters displayed PUSH EBX ; String length PUSH OFFSET STR1 ; String address PUSH EAX ; Output handle CALL WriteConsoleA PUSH 0 CALL ExitProcess ; String - [EBP+08H] ; Length in EBX LENSTR PROC PUSH EBP MOV EBP, ESP PUSH EAX ;------------------- CLD MOV EDI, DWORD PTR [EBP+08H] MOV EBX, EDI MOV ECX, 100 ; Limit the string length XOR AL, AL REPNE SCASB ; Find the 0 character SUB EDI, EBX ; String length including 0 MOV EBX, EDI DEC EBX ;----------------- POP EAX POP EBP RET 4 LENSTR ENDP _TEXT ENDS END START
It should be mentioned that because information is output into the console window, all string constants must be DOS-encoded (or, to be more precise, OEM-encoded; see Chapter 6). Otherwise, this information must be dynamically converted in the course of program execution. Later, I'll explain how to convert programmatically.
Now, I will explain the previously provided programs. When they are started from a command line (e.g., from the Far.exe command line), the "Console application" string will be displayed. When these programs are started as normal Windows applications (e.g., from the My Computer folder), the console window appears for a couple of seconds and then is closed. Why does this happen? Console applications can create their own consoles. If an application creates a console, all input and output uses that console. If the application doesn't create its own console, two kinds of situations are possible. If this application was started from another console, it inherits that console. If, however, the application was started from Windows GUI, Windows creates a console for that application, and this console closes immediately after the application completes its operation.
| ||