This is a college programming assignment in masm32 using kernel32.lib
I'm trying to learn how to use windows API functions in my code, and have been successful with several.
Currently I want to learn how to exit a program without using invoke ExitProcess, 0
I have tried several things and feel I am getting closer, but am hitting a road block. My goal is to
display "Goodbye" to the user for a small amount of time and then exit.
I am currently trying to use
invoke SetConsoleTitleA, near32 ptr currentTitle ; sets current title to Haha
invoke FindWindowA, 0h, near32 ptr currenTitle ; Returns window handle
and then call
invoke SendMessageA,hwnd_window,WM_SYSCOMMAND,SC_CLOSE, 0h
I am trying to use FindWindow to return the handle for SendMessageA; however, I can't even
figure out how to use the return from the function in assembly. I can't find where it's returned to,
or how to set something to the return of the function if that is the case.
I figure i can use SendMessageA to close the console at least.
Any ways I can exit with a displayed string and not just, "Press any key to Continue..."
like I usually get would be of great help.
Assuming that ESP has the same value that it had at entry (IOW, anything that was pushed onto the stack has been removed from the stack), you can set the return value in EAX and use RET.
printf("Bye")
invoke Sleep, 2000
xor eax, eax
ret
I defined the Sleep function and used it correctly. That works beautifully, thank you.
I'm not sure I completely understand the esp, but I think everything is pulled off the stack.
Using 'ret' seems to do the exact same thing as invoke ExitProcess, 0 though. The
"Goodbye" message is displayed, then the 'ret' exits the program and it displays "Press any key to continue..."
Is it a setting I have turned on somewhere? Should ExitProcess even ask to 'press a key to continue..."
or should it just close the console automatically?
"Press any key to continue ..." is what the inkey macro displays. Perhaps I should have added that you cannot do this within a procedure. Here is my full test source:
;==============================================================================
include \masm32\include\masm32rt.inc
;==============================================================================
.data
.code
;==============================================================================
start:
;==============================================================================
printf("Bye")
invoke Sleep, 2000
xor eax, eax
ret
;==============================================================================
end start
And perhaps I should also have added that you probably should not be using the inkey macro in a GUI app.
Also, if you are running the app from a batch file with a PAUSE command then you should see "Press any key to continue . . ." after the app terminates.
The main difference between a simple ret and ExitProcess is that the latter uses a different way out.
ExitProce 8BC0 mov eax, eax ; kernel32.ExitProcess(ExitCode)
75CCBBE4 55 push ebp
75CCBBE5 8BEC mov ebp, esp
75CCBBE7 6A FF push -1
75CCBBE9 68 B0F3E877 push 77E8F3B0
75CCBBEE FF75 08 push dword ptr [ebp+8]
75CCBBF1 FF15 1017C775 call dword ptr [<&ntdll.RtlExitUserProcess
... code never gets here ...
75CCBBF7 E9 ACE40000 jmp 75CDA0A8
BaseThreadInitThunk 8BFF mov edi, edi
75CBED5C 55 push ebp
75CBED5D 8BEC mov ebp, esp
75CBED5F 85C9 test ecx, ecx
75CBED61 0F85 4D010000 jne 75CBEEB4
75CBED67 FF75 08 push dword ptr [ebp+8]
75CBED6A FFD2 call edx << edx=00401000h, ret returns here
75CBED6C 50 push eax
75CBED6D FF15 0C17C775 call dword ptr [<&ntdll.RtlExitUserThread[/color]
RtlExitUserProcess calls NtTerminateProcess
but, i am wondering what is wrong with ExitProcess ??? :P
INVOKE Sleep,-1
it may not terminate, but it will stop doing stuff :biggrin:
CPU Disasm
Address Hex dump Command Comments
00401000 /$ 68 00304000 PUSH OFFSET 00403000 ; /format = "Bye"
00401005 |. FF15 24204000 CALL DWORD PTR DS:[<&msvcrt.printf>] ; \MSVCRT.printf
0040100B |. 83C4 04 ADD ESP,4
0040100E |. 68 D0070000 PUSH 7D0 ; /Time = 2000. ms
00401013 |. E8 28000000 CALL <JMP.&kernel32.Sleep> ; \KERNEL32.Sleep
00401018 |. 33C0 XOR EAX,EAX
0040101A \. C3 RETN
I wonder why this differs ?
Ok, so at my school we have to use the visual studio environment for masm. It just seems like it's how studio exits a program in assembly. It doesn't do this for .cpp or other languages i've used, so I just expected it to be a part of the ExitProcess somehow. I used a different compiler etc... and got it to close successfully. The invoke Sleep, -1
is actually cool if you have to display a long message.
Thank you for your time, I'm still learning so I was having a hard time parsing what you gave me.
If I may, I have another question now. Tell me if I need a new thread or anything else. I'm trying to poll the keyboard for a keypress. Basically..instead of needing to "press enter to continue" I just want to poll most any one keypress. I searched and saw dedndave's procedure but cannot get it to work for some reason. I then tried using invoke WaitForSingleObject, STD_INPUT, 0FFFFFFFFh
....which works great, but leaves the keypress in the buffer. So, after my call to this function, I clear the screen and output a menu...the keypress is recorded in the place I ask the user to choose a menu item. I then searched for functions to clear that from the buffer. I thought invoke FlushConsoleInputBuffer
would work with the correct handle...but it doesn't seem to. Does anyone have an idea of how I could keep that keypress from being recorded?
Quote from: henry.chris on March 02, 2013, 05:57:30 AMDoes anyone have an idea of how I could keep that keypress from being recorded?
As usual there are several ways, but the simplest is probably to use the CRT function _getch():
invoke GetStdHandle,STD_INPUT_HANDLE
invoke FlushConsoleInputBuffer,eax
invoke crt__getch ; reads one char. from input, but does not echo it
My all-time favorite means of Process Termination is: Bug Check (http://msdn.microsoft.com/en-us/library/hh994433(v=vs.85).aspx),...this is especially satisfying if you are drunk.
Here is the MSDN documentation: KeBugCheck routine (http://msdn.microsoft.com/en-us/library/windows/hardware/ff551948(v=vs.85).aspx)
getch is what you want :t
Ok, _getch it is, I tried it before when trying to implement your proc Dedndave...could not get it to work for some reason.
I'll try the bug check routine also just to see what it does. Thank you all for your time.
it may have something to do with the fact it is being called from another thread
i am no C expert, but i think there is a "thread-safe" version of MSVCRT that you can use
one of the C guys may be able to help you more
an alternate approach is to use the keyboard polling routine in a "round-robin" style loop
that way, you don't have to start another thread
Per MSDN "These functions lock the calling thread and are therefore thread-safe."
http://msdn.microsoft.com/en-US/library/078sfkak(v=vs.80).aspx
But the source from the PSDK uses #ifdef _MT to determine whether to lock or not, so the only way to know for sure is to trace it in a debugger (this under Windows XP):
77C2EAA1 8BFF MOV EDI,EDI ; ntdll.7C910228
77C2EAA3 56 PUSH ESI
77C2EAA4 6A 03 PUSH 3
77C2EAA6 E8 10BB0000 CALL msvcrt._lock
77C2EAAB E8 95FDFFFF CALL msvcrt.77C2E845
77C2EAB0 6A 03 PUSH 3
77C2EAB2 8BF0 MOV ESI,EAX
77C2EAB4 E8 60BA0000 CALL msvcrt._unlock
77C2EAB9 59 POP ECX
77C2EABA 59 POP ECX
77C2EABB 8BC6 MOV EAX,ESI
77C2EABD 5E POP ESI
77C2EABE C3 RETN