News:

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

How do I....

Started by chadsxe, March 02, 2007, 06:49:26 PM

Previous topic - Next topic

chadsxe

Let me start off by saying hello as I am new here.  I have programming with C++ for past 4 years and now have entered the world of ASM.  I have a very little amount experince with MASM but have decided to make the switch to GoAsm.  I have been going over the docs for GoAsm and decided my first task was to learn who to write to the console.  This peice of code is from the docs, I added a few data members to it....

;Data section of the app
DATA SECTION
;
KEEP DD 0
;
FIRST_Integer dd 1
SECOND_Integer dd 2

;The main body of the app where the app actually runs
CODE SECTION
START:
PUSH -11
CALL GetStdHandle
PUSH 0,ADDR KEEP
PUSH 24,'Hello World (from GoAsm)'
PUSH EAX
CALL WriteFile
XOR EAX,EAX
RET


My question I guess would be how would I print the values that are in the data members.  Say for example I wanted to print the value that is currently in FIRST_Integer to the console, how is that done?  I making a guess and assuming that I need to find the length of the value and then push that and a pointer to the label. 

Actaully I really have no clue and that is why I am hear...  :P

Thanks

Chad

evlncrn8

easiest api to use -> wsprintf

note its a c call api, so you have to balance the stack on return (add esp,4*amount_of_params_passed)
but its pretty versatile, exported from user32.dll i think...

chadsxe

Quote from: evlncrn8 on March 02, 2007, 07:06:54 PM
easiest api to use -> wsprintf

note its a c call api, so you have to balance the stack on return (add esp,4*amount_of_params_passed)
but its pretty versatile, exported from user32.dll i think...


Yeah..way over my head with that one.  :( Care to explain a little further?

TNick

This is the definition of wsprintf, acording to win32.hlp
Quoteint wsprintf(

    LPTSTR  lpOut,   // address of buffer for output
    LPCTSTR  lpFmt    // address of format-control string
    ...   // optional arguments
   );

(I use MASM syntax here)

So, what you need to do is:
INCLUDE user32.inc
INCLUDELIB user32.lib

...
push OptionalArg1
push OFFSET FrmCtrlStr
push OFFSET TextToOutput ; in C calling convention parameters are pushed from right to left
CALL wsprintf
add   esp, 12 ; 3 arguments => 4*3=12 ; in C calling convention you are responsable to balance the stack

To see how you can use wsprintf, you may use win32.hlp or MSDN, I think.

Regards,
Nick

chadsxe

Wow...I am in way over my head with this one.  I have an idea of what you telling me to do but I am not sure how to actually do it.  Were does  INCLUDE user32.inc INCLUDELIB user32.lib come from?

TNick

To my great shame, I didn't used yet the GoAsm. As I said, I was using the masm syntax. I don't know how things are working with GoAsm.

In MASM, include directive is used to insert the content of a file in another file. In this case, I was sayng to include user32.inc, that contains prototypes for functions that reside in user32.dll. user32.lib is used to properly link your code with user32.dll. After you have done that, you canuse any function from within user32.dll.

But, did you read the specifications for wsprintf function? After you understand that, calling it will be a pice of cake.:)

Regards,
Nick

chadsxe

INCLUDE user32.inc
INCLUDELIB user32.lib

Does this assume that the .lib and .inc are on the c:\ root.   Or do we have to point to it's actual location?

TNick

Sorry, RadASM user! :)

you have to tell the assambler where the includes are
ml ... /I"C:\masm32\include" ...
and to the linker where the lib's are
link ... /LIBPATH:"C:\masm32\lib" ...

Nick

chadsxe

So  if I pulled the user32.inc user32.lib out of the folder you said they were in and put them with my project making sure to update all areas that pointed to them, then I would not have a problem correct?

TNick

Let's make things clear: What I was saing is refering to MASM. You, as I see, are using GoAsm. I told you that I have no ideea on how it works.
If you were using MASM, there was no need to copy those files. You would use either the options that i've indicated for command line, either full paths for them.
But you are NOT. My initial answer's purpose was to show how C calling conversion works (i.e. to complete evlncrn8's answer). However, even if you use GoAsm, you will have to include somehow user32.lib in your exe. So check what options provide the linker that comes with GoAsm.

PS. Damn, I have to take a closer look as soon as possible. :)

Nick

TNick

I saw it now. In GoAsm manual, it says that:
to assamble, you should use

GoAsm /fo ObjFile.obj filename

and to link, you should use

GoLink /console ObjFile.obj kernel32.dll user32.dll

WHERE:
- filename: the file that you assamble
- ObjFile.obj: the generated OBJ file. Name it as your exe
- /console - to produce console program; if you don't want to produce a console program, don't use it
- kernel32.dll and user32.dll: list all dll's that you use function from here, and separate them with a space

So, no need for INCLUDE and INCLUDELIB

Nick

jorgon

Hi chadsxe

Welcome to assembler, and welcome to GoAsm!

Since you are learning assembler, I'm not going to suggest that you do everything using library functions, or Windows functions.  Of course you can use those if you want, for example wsprintfA, but it's fun to write your own functions to do the job!

So you want to print the value that is currently in FIRST_Integer to the console.

The number you have in FIRST_Integer is a zero based number.  In other words if FIRST_Integer is zero its true value will also be zero.  But you want zero to be represented on the screen as "0".  Now "0" is actually a character with a value of 48 decimal or 30 hex when written to the screen in ASCII (the values that the screen understands).  Other characters have other values, for example "Z" is 90 decimal or 5A hex.

So to convert any of these characters to an ASCII value that you can put on the screen you need to add 48 and then write it to the screen.

That would deal with a single digit number, but suppose you have to write the number "10" which is two digits.  Well, if you divide this by 10, you get the result one remainder zero.  If you add 48 to each you can write "0" then "1" to the screen.  Suppose to have to write the number "12".  Well, you divide this by 10, you get the result 1 remainder 2.  Add 48 to each and write "2" then "1" to the screen.  If you have three digits you would need to do a second divide.  But note that each divide gives you get the least significant digit to write (the remainder).  It is only on the last divide that you get the most significant digit.  So the divides give you the digits in reverse order from the order in which they need to be written to the screen.  Therefore you need to reverse them before writing them to the screen. 

The above method works to write a number to the screen, whether using assembler, "C" or any other way.  The method is the same.

To see this working, I would suggest you download the file Testbug from the GoAsm web site.  Run Testbug, click on "speed tests", "comparing asm functions", "writing decimal", then right click to show the help file.  In this help file you will see a decimal converter as described above.  You will also see an example of how to use the wsprintfA function which is a Windows function you can use.

wsprintfA is actually a Windows API within User32.DLL.  You can see that this is so from the Windows Software Development Kit (SDK).  There are instructions how to get the SDK on the GoAsm website.  If you want to use wsprintfA you need to tell GoLink to look in User32.DLL for the function at link-time.
Author of the "Go" tools (GoAsm, GoLink, GoRC, GoBug)

chadsxe

I took your advice and I must say thank you.  Really helped lay a foundation for other stuff.

Regards 

Chad