flat assembler
Message board for the users of flat assembler.

Index > Windows > Using wsprintf

Author
Thread Post new topic Reply to topic
denial



Joined: 12 Sep 2004
Posts: 98
denial
Hello,

again, I'm askin' a question about strings. Is there some kind of tutorial? As newbie, they confuse me alot sometimes. So why does THIS code not work?

Code:
proc _testp
buffer rb 10
enter
cinvoke wsprintf,buffer,'%s',"Hello"
return
endp
    


If I declare "buffer" as global, it works. But declared as local, FASM shows me an error at CINVOKE... So what's the matter here?

Oh and another question: I know that I can translate integers into strings with wsprintf (via %d string). Is there also a possibility to translate floating point values into strings? In C, there was this nice "%f" format string, if I remember right. Smile

Thank you Embarassed
Post 04 Feb 2005, 11:49
View user's profile Send private message Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard
Code:
proc _testp
buffer rb 10
enter
lea eax,[buffer]
cinvoke wsprintf,eax,'%s',"Hello"
return
endp    
Post 04 Feb 2005, 11:56
View user's profile Send private message Visit poster's website Reply with quote
denial



Joined: 12 Sep 2004
Posts: 98
denial
Thank you... Could you maybe explain it shortly, why it's needed?
Post 04 Feb 2005, 12:02
View user's profile Send private message Reply with quote
Madis731



Joined: 25 Sep 2003
Posts: 2140
Location: Estonia
Madis731
Code:
proc _testp
buffer rb 10
enter
cinvoke wsprintf,[buffer],'%s',"Hello" ;Does the trick Wink
return
endp
    
Post 04 Feb 2005, 15:12
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
denial



Joined: 12 Sep 2004
Posts: 98
denial
But in the Win32Help it says, that cinvoke expects a pointer... and why do I need it only when I declare local?

thank you again............
Post 04 Feb 2005, 15:23
View user's profile Send private message Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard
In short, when you declare a global variable, its name means simply its address. But when you declare local variable, for exampe "buffer", its name actually means: "ebp+offset", and you can't push this addres directly on the stack (that's why your code didn't work). You have to load its addres with lea instruction, like in my example.
Post 04 Feb 2005, 15:54
View user's profile Send private message Visit poster's website Reply with quote
denial



Joined: 12 Sep 2004
Posts: 98
denial
Thank you very much, you really helped me Smile
Post 04 Feb 2005, 16:41
View user's profile Send private message Reply with quote
Reverend



Joined: 24 Aug 2004
Posts: 408
Location: Poland
Reverend
denial wrote:
Oh and another question: I know that I can translate integers into strings with wsprintf (via %d string). Is there also a possibility to translate floating point values into strings? In C, there was this nice "%f" format string, if I remember right. Smile

Oh yes there is Razz Recently I wrote a small lib for FASM that has its own sprintf function. It is much more powerful than normal one. I'll just paste a piece of my lib's SDK here, and if you want to get it just go to my website: http://www.reverend.piwko.pl (don't mind it looks like MASM declaration, it's compilable under fasm)

Quote:
sprintf proc C ptrBuffer:DWORD, szFormat:DWORD, ptrArguments:VARARG
- description
This is the greatest proc from this library. It formats strings like the wsprintf API, but it is much more powerful. You have the whole control over formatting. See possible formats below:
%% - saves one '%' character
%d - decimal signed number
%u - decimal unsigned number
%x - hexadecimal unsigned number in lowercase
%X - hexadecimal unsigned number in uppercase
%o - octal unsigned number
%b - binary unsigned number
These were just common formats, but check these below:

BASE64:
%@[len] - saves as result base64 string made from given argument of given lenght in '[]' brackets. These are optional, but if you don't put them proc will assume you have pushed string, so it'll count strlen from it. See examples:
%@ - creates base64 from zero-terminated string
%@[100] - creates base64 from some 100 byte long memory

FLOATING POINT:
ATTENTION: It saves 3 digits after the coma ('.' character')
%fd - floating point decimal signed number
%fu - floating point decimal unsigned number
%fx - floating point hexadecimal unsigned number in lowercase
%fX - floating point hexadecimal unsigned number in uppercase
%fo - floating point octal unsigned number
%fb - floating point binary unsigned number

USER_DEFINED:
%padding/precision[base](sign)+
Yes yes yes. You can define your own formats using this template. First of all put in format string '%' character. After it you can put the 'f' character. If so it treats the number as floating point. After you may put '0x' where x is the number 0-9. If this is floating point number this value indicates number of digits after coma ('.' character). If the number is an integer this value is padding amount, for example '08' will pad the result to eight digits. After it You may put '[xx]' string. Put number in bracket that will be the results base. For example '[2]' for binary, '[10]' for decimal. But it may be only value between 2-16 if more it's truncated. After it you can put '(-)' string to indicate that the number is signed. You can also put only '()' if it's unsigned, but if no '(' character is found sprintf assumes the value as unsigned so it's not needed. At last you can put '+' character to indicate that result shoul be in lowercase, but it applies only to numbers of 11-16 base, because only there alphabetical digits exists. You don't have to put all these things in your-defined format. sprintf will default it to the unsigned decimnal integer. I'll show you some examples to study and understand Smile:
%08[10](-) - pad to 8 digits, decimal, signed
%f[16] - hexadecimal, floatinf point, unsigned, 3 digits after coma (I forgot to say that func defaults number of digits after coma to 3)
%04f[12]+ - 4 digits after coma, base 12, lowercase, floating point

ATTENTION: ALL USER-DEFINED FORMATS MUST END WITH SPACE (' ' CHARACTER)
I hope you have understood it, if no feel free to ask me: rev15@wp.pl

- input
ptrBuffer - some place in memory where to save result
szFormat - string containing formats
ptrArguments - variable length array of arguments

- output
eax: bytes written
Post 05 Feb 2005, 11:56
View user's profile Send private message Visit poster's website Reply with quote
denial



Joined: 12 Sep 2004
Posts: 98
denial
Thank you, I'll give it a try Smile
Post 07 Feb 2005, 12:31
View user's profile Send private message Reply with quote
denial



Joined: 12 Sep 2004
Posts: 98
denial
I've got yet another problem Sad
At the moment I try to understand how pointers in FASM work. So I made a simple application that should display a MessageBox with a given text. But I don't pass the string to the parameters but a pointer named _ptr1, which should refer to the address of the string. However this doesn't work. The app compiles but the messagebox is empty Sad
I tried it like this:

I added some Pseudo-Code comments into the code below that you can understand, what I tried to do. Smile

Code:
include 'include/win32ax.inc'

.code
start:
call _main
invoke ExitProcess,0


proc _main
_ptr1 dd ?
enter
cinvoke wsprintf,buffer,'%s',"Hello!"   ;buffer="Hello"
lea eax,[buffer]
mov [_ptr1],dword eax                     ;_ptr1=&buffer;
pushd 0
cinvoke wsprintf,_str1,'%s',"Caption" 
pushd _str1
lea eax,[_ptr1]
cinvoke wsprintf,_str0,'%s',eax          ;_str0=*_ptr1;
pushd _str0
pushd 0
call [MsgBox]
return
endp

.data
buffer rb 20
_str0 rb 21
_str1 rb 6

section '.idata' import data readable writeable
library user32,'user32.dll',\ 
   kernel32,'kernel32.dll'

import user32,\ 
   MsgBox,'MessageBoxA',\ 
   wsprintf,'wsprintfA'

import kernel32,\ 
   ExitProcess,'ExitProcess'

    



If you could help me, I'd be glad. Smile
Post 08 Feb 2005, 13:01
View user's profile Send private message Reply with quote
Reverend



Joined: 24 Aug 2004
Posts: 408
Location: Poland
Reverend
Quote:
Code:
lea eax,[_ptr1]
cinvoke wsprintf,_str0,'%s',eax          ;_str0=*_ptr1;
    

This is the thing that doesn't work properly. When you write "lea" instruction it sets eax register to ADDRESS of a variable not its CONTENT. And in this case "_ptr1" is somewhere in memory (so its address doesn't interests us), but it CONTAINS the correct address. To make this example work, just change "lea" instruction to "mov", because mov gets the CONTENT of variable
Post 08 Feb 2005, 15:57
View user's profile Send private message Visit poster's website Reply with quote
denial



Joined: 12 Sep 2004
Posts: 98
denial
Oky thank you everything works fine now Smile)
Post 09 Feb 2005, 19:28
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.