I am playing around with Win32 console functions and obviously don't know what I am doing. The following code seems to assemble and link alright but when I try to run it the console window flashes on the screen and disappears.
Is there another function or procedure I need to call to get the window to pause before exiting to the operating system?
include \masm32\include\masm32rt.inc
.data?
bytesWritten DWORD ? ; number of bytes written
.data
endl EQU <0dh,0ah> ;end of line
mesg BYTE "Hello World",0,endl
messagesz = ($-mesg)
consoleHandle DWORD 0
.code
start:
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov consoleHandle, eax
INVOKE WriteConsole,
consoleHandle,
ADDR mesg,
messagesz,
ADDR bytesWritten,
0
INVOKE ExitProcess, 0
end start
Thanks
Maybe you should see how inkey macro works (\masm32\macros\macros.asm). This is the one that does the job in my console programs.
Nick
A couple of options inkey or wait_key
As Nick wrote inkey
inkey
INVOKE ExitProcess, 0
wait_key
INVOKE ExitProcess, 0
The difference, inkey writes the message
Press any key to continue ...
wait_key doesn't show a message,
inkey uses wait_key to wait for a key press.
Thanks TNick and dsouza123 that makes it do what I wanted. :U
I'll take a look at the macros to see how they work.
inkey is a rather nasty hack IMO, and requires the crt and a loop function. I would recommend setting the console mode to ENABLE_PROCESSED_INPUT and reading a single character from stdin. That requires only winapi and no loop.
Ehtyar.
Quote
inkey is a rather nasty hack IMO, and requires the crt and a loop function. I would recommend setting the console mode to ENABLE_PROCESSED_INPUT and reading a single character from stdin. That requires only winapi and no loop.
To duplicate even most of the functionality of wait_key your method would require calls to GetStdHandle, SetConsoleMode, FlushConsoleInputBuffer, and ReadConsole or ReadFile, plus a buffer, and additional code to move the returned character into EAX. And after all of this it still would not respond to the escape, function, or navigation keys as wait_key does.
Which is...
ConsoleIn proc lpbuffer:DWORD,bufflen:DWORD
; -----------------------------------------------------------
; lpbuffer should be 260 bytes on win2k and later os versions
; -----------------------------------------------------------
LOCAL stdhandle :DWORD
LOCAL readcount :DWORD
invoke GetStdHandle,STD_INPUT_HANDLE
mov stdhandle, eax
invoke SetConsoleMode,stdhandle,ENABLE_LINE_INPUT or \
ENABLE_ECHO_INPUT or \
ENABLE_PROCESSED_INPUT
invoke ReadFile,stdhandle,lpbuffer,bufflen,ADDR readcount,NULL
; ---------------
; strip CRLF pair
; ---------------
mov eax, lpbuffer
sub eax, 1
@@:
add eax, 1
cmp BYTE PTR [eax], 0
jz @F
cmp BYTE PTR [eax], 13
je @F
cmp BYTE PTR [eax], 10
ja @B
@@:
mov BYTE PTR [eax], 0
sub eax, lpbuffer
ret
ConsoleIn endp
Not too bad, in my opinion. It is in my library. All the user has to supply is a buffer and its length. :U
Paul
How about
WaitForKey PROC uses edi
invoke GetStdHandle,STD_INPUT_HANDLE
mov edi,eax
invoke WaitForSingleObject,edi,INFINITE
invoke FlushConsoleInputBuffer,edi
ret
WaitForKey ENDP
Quote from: Ehtyarinkey is a rather nasty hack IMO, and requires the crt and a loop function.
I disagree. There's nothing wrong with using the CRT, it's just another Windows DLL that can be called. No different than calling the Windows API. Granted, the CRT functions aren't the best for speed, but for functionality and stability they are pretty darn good. The CRT has withstood the test of time.
Quote from: sinsi on March 04, 2007, 12:51:34 AM
How about
WaitForKey PROC uses edi
invoke GetStdHandle,STD_INPUT_HANDLE
mov edi,eax
invoke WaitForSingleObject,edi,INFINITE
invoke FlushConsoleInputBuffer,edi
ret
WaitForKey ENDP
Well i sure as hell love that, thanks sinsi, that is some awesome code :)
Quote from: MichaelW on March 03, 2007, 09:17:34 PMQuoteinkey is a rather nasty hack IMO, and requires the crt and a loop function. I would recommend setting the console mode to ENABLE_PROCESSED_INPUT and reading a single character from stdin. That requires only winapi and no loop.
To duplicate even most of the functionality of wait_key your method would require calls to GetStdHandle, SetConsoleMode, FlushConsoleInputBuffer, and ReadConsole or ReadFile, plus a buffer, and additional code to move the returned character into EAX. And after all of this it still would not respond to the escape, function, or navigation keys as wait_key does.
You'll forgive me if i was a little vague. What i mean to say is that if you're not using the crt to begin with (i almost never do, thus my bias in this case) it's not very nice to have to include extra dependencies just for a function this simple. (and why is a loop required if you're not using the return value anyway?)
Ehtyar.
Quote from: Ehtyar on March 04, 2007, 03:40:59 AM
Well i sure as hell love that, thanks sinsi, that is some awesome code :)
Why thankyou :bg
I was looking for something as simple as "sub ah,ah; int 16h" and a few beers later up it popped :bdg
Quote from: Greg on March 04, 2007, 01:27:25 AM
Quote from: Ehtyarinkey is a rather nasty hack IMO, and requires the crt and a loop function.
I disagree. There's nothing wrong with using the CRT, it's just another Windows DLL that can be called. No different than calling the Windows API. Granted, the CRT functions aren't the best for speed, but for functionality and stability they are pretty darn good. The CRT has withstood the test of time.
The CRT simply calls the Win32 API functions. It's not 'just another Windows DLL', it's a wrapper around the Windows API and some extra functionality which isn't part of the API. If you desperately want this extra functionality, go ahead. If you don't, the Windows API route is much more efficient.
Sinsi,
Love your code, that's even better than my variant. I've thrown it into ASM Runtime if that's okay with you?
Cheers,
Zooba :U
Quote from: zooba on March 04, 2007, 05:32:26 AM
Sinsi,
Love your code, that's even better than my variant. I've thrown it into ASM Runtime if that's okay with you?
Cheers,
Zooba :U
No, this is my own personal code...heh heh.
Of course you can use it - anyone can do anything they want with it (except blame me) :U
Go for it!
Quote from: sinsi on March 04, 2007, 12:51:34 AM
How about
WaitForKey PROC uses edi
invoke GetStdHandle,STD_INPUT_HANDLE
mov edi,eax
invoke WaitForSingleObject,edi,INFINITE
invoke FlushConsoleInputBuffer,edi
ret
WaitForKey ENDP
Good idea, but I see two problems. The first is that the input buffer is not being flushed before the call to WaitForSingleObject, so the code will not wait if there is anything in the input buffer. The second is that WaitForSingleObject responds to the key-release event. If you do two calls to the procedure without a significant delay between the calls, even with a call to FlushConsoleInputBuffer placed ahead of the call to WaitForSingleObject, the second call will not wait.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
WaitForKey PROC uses edi
invoke GetStdHandle,STD_INPUT_HANDLE
mov edi,eax
invoke FlushConsoleInputBuffer,edi
invoke WaitForSingleObject,edi,INFINITE
invoke FlushConsoleInputBuffer,edi
ret
WaitForKey ENDP
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke WaitForKey
print "1",13,10
invoke WaitForKey
print "2",13,10
invoke wait_key
print "1",13,10
invoke wait_key
print "2",13,10
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
I have seen these odd purist comments before about predispositions of which system DLLs should be used and which should be ignored but its hard to argue a case of efficiency when an application is doing no more than waiting on a keystroke. MSVCRT.DLL has been a Windows component since win95b and it is very reliable.
Contrary to popular opinion, a polling loop with a published wait function (Sleep) is extremely efficient in terms of processor usage as it only does a periodic test for the keystroke and yields to the OS for the rest of the time. If this was a performance critical issue you would look for the most efficient way to perform the task but it is still no more than waiting for a keystroke and as its doubtful that anyone can hit any key fast enough to beat the keyboard repeat rate let alone do something that actually changes the processor usage.
I am in debt to Greg for his original design work from MSVCRT for the procedure that is simple, fast and reliable.
Quote from: Ehtyar on March 04, 2007, 03:40:59 AM
(and why is a loop required if you're not using the return value anyway?)
The loop waits for a key press, with essentially a CPU utilization of zero. The call to crt__getch removes the keystroke from the buffer, leaving it empty, and returns the key character.
To me, "nasty hack" describes code that is ill designed and unreliable. The wait_key procedure is neither.
Thanks to everyone for the input and great code samples! This gives me a lot of information to digest and more code to play around with. :P
I can see advantages in each, ranging from simplicity to functionality.
Well, I don't "desperately want" the extra functionality but there are times when it's the best option.
I prefer to use the Windows API, but there are times when recreating the functionality of a C Run-Time function is not worth it. The CRT functions work and have been exhaustively tested over the years. If you are looking for maximum speed, you probably don't want to use a CRT function. If you are looking for reliability and stability and the Windows API doesn't offer the functionality you need, they are a good way to go.
I know I will never convince the "purists" around here. If you don't want to use the CRT functions, fine, don't use them, but criticizing people for using them is out of line.
Greg,
Very well said.
Paul
OK, maybe I didn't have enough beers :(
WaitForKey PROC uses edi
invoke GetStdHandle,STD_INPUT_HANDLE
mov edi,eax
invoke FlushConsoleInputBuffer,edi ;make sure there are no keystrokes
invoke WaitForSingleObject,edi,INFINITE ;wait for a key down
invoke FlushConsoleInputBuffer,edi ;remove the keydown so it doesn't echo
invoke WaitForSingleObject,edi,INFINITE ;wait for a key up
invoke FlushConsoleInputBuffer,edi ;remove the keyup so it doesn't echo
ret
WaitForKey ENDP
Now it's getting a bit too complicated (and maybe a bit too long time-wise?).
And there is the problem of a key held down and repeating...
I must admit I don't use CRT at all - it seems a bit much to load a big DLL just to use one function - but that is my personal preference.
Why isn't there a PressAnyKey function in kernel32 boo hoo.
The above un-pauses when I mouse-over the CUI window. :lol
I had to add:
invoke SetConsoleMode,hConsoleInput,ENABLE_LINE_INPUT or \
ENABLE_ECHO_INPUT or \
ENABLE_PROCESSED_INPUT