Hi.
I'm new to assember but I have programmed in different languages before. My question is, hopefully, very simple. Do I have to put all the strings I plan to use in the data section?
I wanted a MessageBox to display either 'True' or 'False' depending on whether a function returned (I've been trying to get some resource thing working in every language I know so I wanted to see if it worked in assembler) and I tried having an empty string stored in the data? section and setting it to either True or False in an If statement. I tried:
mov BoxText, "True"
and
push "True"
pop BoxText
But neither of them work. (I also tried using '=' because it was late at night and I slipped back in to my old ways ::))
Is there a way of doing this or do I have to declare variables that hold True and False and use them?
Thanks,
Matthew
no you dont, because there are .const, .data, .code sections to put any data (the first and last only for reading) besides you can use resources to hold the readable data including strings.
MattVonFat,
In assembler, you must put all your data (strings, constants etc) in special section called .data or .data? if they are not initialised.
So your "true" and "false" strings should be defined in .data like follows:
.data
True BYTE "True",0
False BYTE "False",0
All text variables must be ended with NULL sign in Windows (if you want MessageBox to show only the text which you want to show).
If you are c++ programmer, I know what you think now - why MessageBox,0,"Hi there", "My App", MB_OK doesn't work. But you must face at true, c++ compiler always putting all variables in one place (section) of program and exchange them in function calling with they addresses, now you can do it yourself :toothy.
Welcome in masm32 forum & good luck :U
AsmER
;If I said something wrong, please correct me immediately
AsmER said it right, except the word "must" i would say CAN. with assembly you can do anything that hardware allows, even storing your data in a .code section;) if you want of course. there is nothing impossible because "there is no spoon";)
Quote from: MattVonFat on March 14, 2006, 05:55:31 PM
mov BoxText, "True"
push "True"
pop BoxText
Hello Matthew and welcome. I believe you're thinking a little too high-level here. To actually display a string such as "True" and "False" in MASM32, it does require the strings to be pre-defined. As others have said this is accomplished easily:
.data
szFalse db "False",0
szTrue db "True",0
The .DATA directive tells MASM that the items following are INITALIZED data elements, which means they are stored inside the executable file as linear data bytes. This is what you want so you can access them at run-time. You can't put these variables in the .DATA? section because that section is for UNINITIALIZED data - which means anything defined in there is
not saved in the file. The .DATA? section is used primarily for things like temporary strings and buffers and whatnot - stuff that doesn't have to be preset with any data when the file is ran.
If you'd like to pop up a messagebox with the word "Pass" or "Fail" in it, try tinkering with this:
include masm32rt.inc ; all the standard compile-time libraries
.data
szFalse db "False",0 ; the ",0" appends a NULL to the string
szTrue db "True",0 ; which is necessary to meet ASCII specs.
szTitle db "Condition:",0 ; messagebox title string
.code
start:
invoke MessageBox,0,addr szTrue,addr szTitle,MB_OK
invoke MessageBox,0,addr szFalse,addr szTitle,MB_OK
invoke ExitProcess,0
end start
That said, the ASMINTRO.HLP file included with MASM32 has a lot of really good info in it. Take a peek there and check out the \examples and \icztutes folders for lots more good stuff. Take care and have fun! :bg
Yes variables can be even in
.code section but programmer must take care, to don't let proccessor read them as an instruction. i.e:
.code
start:
...
jmp AfterData
My_data db "....."
AfterData:
...
END start
or
.code
...
call QuitProcedure
MyData db "..." ;it can be here because program will be ended at previous line
Quote...there is nothing impossible because "there is no spoon";)
- I like that :bg. asmfan cheers for correction.
AsmER
[a simple straightforward answer :toothy]
The way strings are actually used is that you store them all in the data section and then 'point' to the one you want.
This is exactly what happens in 'higher' languages, but it's done magically for you.
So, for showing true or false you have two options..
Firstly, your strings go in the data section (sorry, not much choice there :bdg)
.data
yep db "True",0
nope db "False",0
And then you can either choose which messagebox to show depending on your outcome:
call mymagicfunction
.IF (eax)
invoke MessageBox, NULL,ADDR yep,ADDR blah,MB_OK
.ELSE
invoke MessageBox, NULL,ADDR nope,ADDR blah,MB_OK
.ENDIF
..or, you can get the pointer for the required string and then print the one you end up pointing to:
call mymagicfunction
.IF (eax)
mov ecx,OFFSET yep
.ELSE
mov ecx,OFFSET nope
.ENDIF
invoke MessageBox, NULL,ecx,ADDR blah,MB_OK
(equally, you could store the pointer in some variable instead of ecx.)
Thanks for all the help on this!
I edited the program and it worked perfectly!
Thanks again,
Matt
Matt,
There is an even simpler way once you understand how the string data is stored in an assembler EXE file. MASM32 has a reasonable number of macros (masm is a macro assembler) and these are designed to make simple tasks simple to perform.
The "fn" macro allows you to do this.
fn MessageBox,hWnd,"Hi, I am a message box","Info",MB_OK
All it does is place quoted text directly into the .DATA section and when you know a bit more about assembler, all of the source for both the library and the macros are available for you to read.
By including the packaged predefined macros you can do this for example:
call mymagicfunction
.if(eax)
invoke MessageBox, NULL,SADD("Yep"),SADD("Message"),MB_OK
.else
invoke MessageBox, NULL,SADD("Nope"),SADD("Message"),MB_OK
.endif
That effectively does what I think you want, but the SADD macro itself eventually uses a .data section, you just don't see it.
Chris
Yet another way.
A very short lookup table with the answer string determined by the result of the function.
If your function returns only 0 or 1 for results, or can be transformed to the range by using AND,
with the result in the eax register (a fairly standard convention) this will work.
0 in eax will map to False, 1 to True.
The answer will be padded with 2 or 3 trailing spaces.
.data
szAnswer db "False ",0
db "True ",0
szCaption db "MessageBox Caption",0
.code
invoke Somefunction ; and eax, 1 ; Optional, this will transform the result to a value of 0 or 1
lea ecx, dword ptr [szAnswer + eax*8]
invoke MessageBox,0,ecx,addr szCaption,MB_OK
A minor alteration removes the trailing padding spaces.
The trick is to have each answer take 8 bytes, including a 0 byte to zero terminate each string.
.data
szAnswer db "False", 0,0,0
db "True",0,0,0,0
There is another option a which involves a list of strings
and an array of pointers to the strings.
It will also use the calculation method using results of 0,1,2 (for 3 strings).
.data
szNo db "No",0
szYes db "Yes",0
szMaybe db "Maybe",0
pStrTable dd szNo,szYes,szMaybe
.code
invoke Somefunction
mov ecx, [pStrTable + eax*4]
invoke MessageBox,0,ecx,addr szCaption,MB_OK
There's nothing like complicating matters :green
What this post proves is that there's more than one (fifty!!) way(s) to do something.
Also, that when you ask a bunch of asmers a simple question, they will tell you the fifty ways of doing it.
Anyway, if in doubt - keep it simple, stupid :toothy
Wow, so many choices :eek. I think i'll take Tedd's advice and stay simple for now and just declare separate variables for each string myself. Although dsouza123's method seems the most fun!
Thanks everyone,
Matthew