I have a number of procs which all begin :-
LOCAL hOutPut:DWORD
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hOutPut,eax
Is there any advantage in making this Handle Global i.e. doing it only once at the beginning of the program & thus doing away with all the GetStdHandle handle calls.
Yes, you can make it global to avoid multiple calls to GetStdHandle
Thanks Vortex, why I had my doubts was because I was taught that it was good practice to release a handle as soon as it was finished with.
Hi Neil,
You are welcome.
You can have a look at the source code of StdOut.asm, it does not release the handle at the end :
StdOut proc lpszText:DWORD
LOCAL hOutPut :DWORD
LOCAL bWritten :DWORD
LOCAL sl :DWORD
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hOutPut, eax
invoke StrLen,lpszText
mov sl, eax
invoke WriteFile,hOutPut,lpszText,sl,ADDR bWritten,NULL
mov eax, bWritten
ret
StdOut endp
Quote from: Neil on November 27, 2008, 11:54:44 AM
I was taught that it was good practice to release a handle as soon as it was finished with.
That's right, but you're not finished with it until you've finished printing text to the console :wink
The handle actually exists whether you use it or not - it's created when the program is loaded (which is why you have to link as a console program; or you must AllocConsole yourself to create it.) You didn't actually create it, so you're not the one destroying it either. Apply that rule to handles you specifically create, e.g. file handles, graphic objects, etc.
Thanks Vortex & Tedd for clearing that one up :thumbu
In keeping with the way "they" teach, the preferred method might be to get the handle once, in the beggining, and then pass it to each function that needs to print as an argument, in lieu of accessing the global varaible directly from each WriteFile() line.
-alan
I think the MASM32 "print" macro gets this handle every time it is used. When I would run a MASM32 console program through MemProof (a memory leak tool, search here) it would report many such "unfreed handles." However Tedd is correct, when we "GetStdHandle" it is not actually creating a handle, just giving us the handle which is already there. Thus, perhaps a few clock cycles could be saved if we get this handle once and referr to it globally.
Here is a basic routine in GoASM syntax, which outputs unicode text. If "threaded" is defined (#define threaded), it becomes thread-safe, meaning two or more threads from the same process cannot write text to the output at the same time.
.data
CSect CRITICAL_SECTION<> ; threading info
.code
coutt frame hConsole,lpTextW ; console-out (threaded)
local n ; returns nChars as eax
#ifdef threaded
invoke EnterCriticalSection,addr CSect ; only allow one at a time
#endif
xor eax,eax ; get length of text arg
mov ecx,[lpTextW]
: cmp w[ecx+eax],0
jz >
add eax,2
jmp <
: shr eax,1 ; eax = n unicode chars
invoke WriteConsole,[hConsole],[lpTextW],eax,addr n,0
#ifdef threaded
invoke LeaveCriticalSection,addr CSect
#endif
mov eax,[n]
ret
endf
Use as:
.data
align 4
hCin dd ? ; console handles
hCout dd ?
hCerr dd ?
wMyString dw "Hello World from UNICODE land!",13,10,0
.code
start:
invoke GetStdHandle,STD_INPUT_HANDLE ; get console handles (once)
mov [hCin],eax
invoke GetStdHandle,STD_ERROR_HANDLE
mov [hCerr],eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [hCout],eax
invoke SetConsoleMode,[hCin],ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT
invoke coutt,[hCout],addr wMyString ; print desired text to hCout
; number of characters written returned in EAX