flat assembler
Message board for the users of flat assembler.

Index > Main > Basic arithmetic | Integer to string conversion

Author
Thread Post new topic Reply to topic
flat_fiat



Joined: 01 Nov 2011
Posts: 5
Location: Kansas City, USA
flat_fiat
Hi everyone,

I'm pretty new to assembly and am just making small programs to help me learn while reading manuals. Anyway, I seem to have hit a wall dealing with basic addition. I'm trying to add two numbers and display the sum in a messagebox. However, I feel like I'm not doing it "the correct way" because it only works if the sum is a single digit.

It seems like there is a better way to go about it?

Code:
include 'win32ax.inc'

.data

  result  dd ?
  Caption db 'Result of eax',0


.code

  start:
        mov eax,'1'
        add eax,'2'
        mov [result],eax

        sub [result],48

        push MB_OK
        push Caption
        push result
        push NULL
        call [MessageBox]

        push 0
        call [ExitProcess]

.end start    
Post 06 Dec 2011, 18:00
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1419
Location: Toronto, Canada
AsmGuru62
You need to convert the result from a register (say EAX) into a string, which can be shown in a dialog. It is done by a function wsprintf(), which comes as import from USER32.DLL. Also, your code is responsible for cleaning the stack after the call.
Code:
strFormat       db 'THE RESULT IS: %d',0
strTitle      db 'RESULT OF ADDITION',0
strBuffer        rb 64
...
mov     eax, 53627
add       eax, 73893
invoke    wsprintf, strBuffer, strFormat, eax
add      esp, 3*4

invoke  MessageBox, 0, strBuffer, strTitle, MB_OK
    
Post 06 Dec 2011, 18:19
View user's profile Send private message Send e-mail Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Code:
invoke  wsprintf, strBuffer, strFormat, eax
add     esp, 3*4    
=
Code:
cinvoke wsprintf, strBuffer, strFormat, eax ; Notice the leading c    

AsmGuru62's code is fine and there is no reason not to use it, but still for exercising purposes I'd recommend you try to port itoa to Assembly (although not necessarily exactly as it appears, just something that produces the same string as output).
Post 06 Dec 2011, 19:07
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1419
Location: Toronto, Canada
AsmGuru62
Yep! cinvoke is better - less lines.
Post 06 Dec 2011, 21:14
View user's profile Send private message Send e-mail Reply with quote
flat_fiat



Joined: 01 Nov 2011
Posts: 5
Location: Kansas City, USA
flat_fiat
AsmGuru62 wrote:
... Also, your code is responsible for cleaning the stack after the call.


Thanks. One more question...since my program terminates immediately after showing the sum, there's no need for me to clean up the stack, right? When Windows terminates the process all allocated memory my program was using is freed. Am I thinking of this correctly?
Post 06 Dec 2011, 22:08
View user's profile Send private message Reply with quote
Tyler



Joined: 19 Nov 2009
Posts: 1216
Location: NC, USA
Tyler
Yes. All the memory gets freed when the program terminates and there's no need to worry about cleaning the stack, since all the memory is freed. (Not that cleaning the stack is the same as freeing other memory.)
Post 06 Dec 2011, 22:25
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1419
Location: Toronto, Canada
AsmGuru62
If you put that code (where you invoke wsprintf) into a separate procedure, then you do need to clean the stack. But in that specific case above - no need.
Post 07 Dec 2011, 15:12
View user's profile Send private message Send e-mail Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
> sub [result],48

ADD maybe ??? Also ZERO-terminate the string.

> You need to convert the result from a register (say EAX) into a string,
> which can be shown in a dialog. It is done by a function wsprintf()

Or write your own or find one http://board.flatassembler.net/topic.php?t=9494 "number_to_string_dec"
Post 12 Dec 2011, 02:31
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Quote:

ADD maybe ??? Also ZERO-terminate the string.

No, notice that both operands are characters so by subtracting he gets the correct answer (also null terminated since he works with the entire dword). Obviously this doesn't work if the result cannot be represented in a single decimal digit.
Post 12 Dec 2011, 03:37
View user's profile Send private message Reply with quote
Overflowz



Joined: 03 Sep 2010
Posts: 1046
Overflowz
Code:
mov eax,'1' ;EAX = 31
add eax,'2' ;EAX = 31+32=63    

so, numbers are from 30 to 39 (in ASCII)
you should first convert it to decimal, add them together and then convert again to ascii.
Post 12 Dec 2011, 07:48
View user's profile Send private message Reply with quote
flat_fiat



Joined: 01 Nov 2011
Posts: 5
Location: Kansas City, USA
flat_fiat
AsmGuru62 wrote:
You need to convert the result from a register (say EAX) into a string, which can be shown in a dialog. It is done by a function wsprintf()....

While I was pondering this function, I was thinking "...Why do I need to manually specify the buffer?...That seems like it could be bad...Wouldn't it be better if the function took care of that automatically?..."

So I looked up the function in Microsoft's MSDN and sure enough, they recommend not using it and instead using alternatives such as StringCbPrintf.

So my question is, why was wsprintf implemented the way it was as opposed to other functions like StringCbPrintf, which appear to be a better (as in safer) way of doing things? I guess wsprintf was a general 'do-it-all' function whereas the others like StringCbPrintf are much more narrow in scope?
Post 12 Dec 2011, 19:29
View user's profile Send private message Reply with quote
bdo1964



Joined: 18 Sep 2011
Posts: 7
bdo1964
here is an example

Code:
include 'win32a.inc'
format PE console 4.0
entry start
;*********************************************
section '.data' data readable writeable
;*********************************************
v1      db '999999999999999999',0
v2       db '000099999999999999',0 ;must have same len as v1!!!
;          ^^^^                      <-left pad with zero's!!!
vv    db '0000000000000000000',0 ;<-vv must have len v1+1!!!
tit      db 'v1+v2='
x      dd 0
; v1+v2 =   1000099999999999998
;*********************************************
nl db 0
_s db '%s',13,0
_i db '%i',13,0
_x db '%08X ',13,0
;*********************************************
section '.text' code readable executable
;*********************************************
proc        strlen stdcall str:dword
xor     ecx,ecx
xor  eax,eax
mov  ebx,[str]
strlen_loop:
mov    al,byte[ebx]
cmp     al,0
jz      strlen_is_null_byte
inc      ecx
inc      ebx
jmp      strlen_loop
strlen_is_null_byte:
xor  eax,eax
mov  eax,ecx
ret
endp

;*********************************************
start:                      ;fasm_bn_add.fasm

stdcall strlen,v1              ;note: only v1's length is determined

mov   ecx,eax                 ;therefore v2 must have the same length
                             ;thus we would left pad v2 with zero's
xor  eax,eax
xor  ebx,ebx
add_digits:
xor       eax,eax
mov  ah,byte[v1+ecx-1]
add        al,byte[v2+ecx-1]
and        ax,$0f0f
mov bh,ah
add    bh,al
add    bh,bl                   ;bh=ah+al+carry(bl)
mov      byte[x],bl
mov       byte[x],bh
cmp       bh,10
jb     zero_carry              ;carry(bl)=1
mov     bl,1
sub     bh,10
jmp    past_zero_carry
zero_carry:
mov       bl,0
past_zero_carry:
or      bh,$30
mov   byte[vv+ecx],bh
dec  ecx
jnz      add_digits
cmp       bl,1
jb      no_final_carry
mov   byte[vv],$31
no_final_carry:

;*********************************************
; invoke  MessageBox,0,vv,tit,0
cinvoke printf,_s,vv;vv = 1000099999999999998
invoke  ExitProcess,0
;***********************************************
section '.idata' data import readable writeable
  library kernel32,'kernel32.dll',\
          user32,'user32.dll',\
          msvcrt,'msvcrt.dll'
  include 'api\kernel32.inc'
  include 'api\user32.inc'
  import msvcrt,\
         printf,'printf'
;***********************************************

    

_________________
briano


Last edited by bdo1964 on 15 Dec 2011, 05:34; edited 2 times in total
Post 12 Dec 2011, 22:52
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1901
DOS386
> No, notice that both operands are characters so by subtracting

Damn Sad
Post 13 Dec 2011, 09:02
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17658
Location: In your JS exploiting you and your system
revolution
flat_fiat wrote:
So my question is, why was wsprintf implemented the way it was as opposed to other functions like StringCbPrintf, which appear to be a better (as in safer) way of doing things? I guess wsprintf was a general 'do-it-all' function whereas the others like StringCbPrintf are much more narrow in scope?
Generally speaking, asking such questions is well beyond the scope of this forum since nobody here knows the real reasons why MS do things (and if they do know they are not going to be saying here). But that aside I am willing to speculate that the reason is because wsprintf is a very old function stemming from at least the Win3.1 times when "safety" was not a concern and OS functions were more limited and simpler. Functions like StringCbPrintf came much later and won't be found on older OSes like Win95 or Win2000 so might create a problem if you need to support older systems. It is certainly up to you which function you like to use, just be sure that you understand the potential problems of using them.
Post 13 Dec 2011, 09:11
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1419
Location: Toronto, Canada
AsmGuru62
M$ recommends not to use these functions because today's coders are way too primitive and their code is easily "buffer overflowable"!
Post 13 Dec 2011, 18:08
View user's profile Send private message Send e-mail 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.