News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

/system:(windows or console) ?

Started by thomas_remkus, June 14, 2005, 10:10:22 PM

Previous topic - Next topic

thomas_remkus

I wrote a windows application, very simple, and used the StdOut. I used "/system:windows" and nothing showed. I then used "/system:console" and there it was. My window popped up along with a console window. Now, this is the first time I have experimented with this so it's a little strange because the console version also popped up a console and output some text.

Now, when I would be debugging this could be really exciting, so is there a way to turn this console on/off with the same one executable? I did a compare and it seems that the only difference is a PE header bit. Am I right? So I could basically write all my applications with "/system:windows" and still use StdOut. Then only when I wanted to see the output I could close the image, change the PE, and rerun the application for console output.

PLEASE NOTE !!!!! This is for experimentation only !!! I am not suggesting that production code is written with this in mind, only that it's a possible strange technique.

thomas

Mark Jones

Hi Thomas. It's my experience that the two systems differ greatly in usage. While it may be possible to edit the PE header to force an app to run in the other mode, usually this has no advantage because the code itself will not run in that mode; i.e., adding buttons to a console is impossible. :) But if the code is explicitly creating a window, (subclassed CreateWindowEx?)  then maybe they both could exist at the same time.

I started out with the Iczelion GUI tutorials (in \MASM32\tutorials), but find console apps to be much simpler. I'm surprised someone hasn't suggested that newcomers start out with console apps instead, but perhaps it is considered extraneous knowledge since most people want to build windows GUI apps. But it might be a good way to get your feet wet. :) Mark Larson, Hutch, and Michael W. are constantly posting cool little console test pieces in the workshop and lab to experiment with. I have a saying: "If necessity is the mother of invention, then is experimentation it's father?"  :bg

Since it seems like what you're really after is some way to "debug" the code, here are some ways to get feedback from code exectution (off the top of my head):


include macros.asm
.code
; put this where you want a popup message in GUI app
szText szTitle,"Testing 123!"
szText szCaption,"This is a test!"
invoke MessageBox,0,addr szCaption,addr szTitle,MB_OK


One of my favorites is a simple beep. They work in either system and you can make them different frequencies and durations to hear what code is executing. :)

.code
invoke Beep,100,1000  ; 100Hz tone for 1000ms (1sec) (oops sound)


Of course, loading the .exe into your favorite debugger is another way to see what is going on. Load it into OllyDbg and keep pressing F8. :U
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

thomas_remkus

Let me back this out a little then and talk about a problem that I am actually having. This is a really silly example.

.486
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib

.data?
CommandLine LPSTR ?

.code
start:
    invoke GetCommandLine
    mov CommandLine, eax
    invoke MessageBox, 0, offset CommandLine, offset CommandLine, 32
    invoke ExitProcess, eax
end start

This just gives me trash.  However, if I change the MessageBox line to:

push 32
push CommandLine
push CommandLine
push 0
call MessageBox

Then I get exactly what I was expecting before. This is an issue I have been strugling with I just can't seem to get over right now.  Now, if I change this line again I can get it to work if I put in this:

    invoke MessageBox, 0, [CommandLine], [CommandLine], 32

And then that works perfectly. Now, you might ask, how did I get that syntax ... well, some piece of information is stuck in the back of my head from years ago when I attempted to study this and I remembered that sometimes there were square brackets but I can't remember why.

frustrated,
thomas

PS: I don't know how you get those cool looking code blocks.

chep

Thomas,

Quote from: thomas_remkus on June 14, 2005, 11:51:39 PM
This is an issue I have been strugling with I just can't seem to get over right now.  Now, if I change this line again I can get it to work if I put in this:

    invoke MessageBox, 0, [CommandLine], [CommandLine], 32

You don't need the square brackets around CommandLine. This will also work :
    invoke MessageBox, 0, CommandLine, CommandLine, 32

Your problem came from that with
    invoke MessageBox, 0, offset CommandLine, offset CommandLine, 32
you were pushing the *address* of the CommandLine variable not its *contents*, so MessageBox tried to display a string beginning at *offset* CommandLine.

Both
    invoke MessageBox, 0, [CommandLine], [CommandLine], 32
and
    invoke MessageBox, 0, CommandLine, CommandLine, 32
push the contents of the variable, ie. the value returned by GetCommandLine.


Quote from: thomas_remkus on June 14, 2005, 11:51:39 PM
PS: I don't know how you get those cool looking code blocks.
Use the button figuring a #, which is located above the smiley bar. :wink


Concerning your original question about a mixed GUI / console application, I'll post an example shortly.

<edit>
Here it is :

.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE

INCLUDE \masm32\include\kernel32.inc
INCLUDE \masm32\include\user32.inc
INCLUDE \masm32\include\masm32.inc
INCLUDE \masm32\macros\macros.asm

INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\user32.lib
INCLUDELIB \masm32\lib\masm32.lib

.DATA
DEBUG_HASCONSOLE equ 1

szMessage db "Hello world!",0

.CODE
EntryPoint:

  IF DEBUG_HASCONSOLE
    invoke  AllocConsole                           ; Create a new console
  ENDIF

  print   ADDR szMessage                           ; Console output
  invoke  MessageBoxA, 0, ADDR szMessage, 0, 0     ; GUI "application"
  ret

END EntryPoint


This must be compiled using /subsystem:windows.

If you set DEBUG_HASCONSOLE to 0, you'll have no console output.
If you set it to 1, a *new* console will be created so the message will output.
AFAIK this is not possible to inherit the parent console, as you are in a GUI application.

Of course it would be a good idea to either :
- surround all console statements by conditional compilation directives (IF DEBUG_HASCONSOLE) so that changing the DEBUG_HASCONSOLE value can give you either a "debug" or an optimized "release" build
- or surround all console statements by runtime conditionals that could be enabled by a command line argument
(my preference going to the first solution)

Hope this helps...
</edit>

thomas_remkus

Shoot ... darned if you arn't right. I thought that I tried it that way and it errored or gave me silly data. Yup, it's giving me the right data now. Strange ... but it's right.

I know in limits what the "invoke" thing does and I should have realized what my mistake was.