Trying to print out a number, problem with stopping printing...

  • Follow


Using masm32 on windows vista.
It prints the correct result,720 and then a bunch of gibberish.
I should delimit the string with ~ I think but I'm not sure and not
sure how to do it.
Also shouldn't it just stop printing after 3 chars?
I preferrably want to move everything into a buffer and print it at
once instead.
Using edi I guess?
I have really tried to get this working but googling does give
anything.




;
#########################################################################

      .386
      .model flat, stdcall
      option casemap :none

;
#########################################################################

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

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

;
#########################################################################

..data
    N sdword 6
    Acc sdword 0
    ;IntArray        dword 8 dup (?)

..code
start:
    mov ecx, N
    mov eax, 1
_fac:
    mul ecx
    loop _fac


 utoa:
    mov ebx, 10 ; we'll divide by this
    xor ecx, ecx ; use as digit-counter
 pushloop:
    xor edx, edx
    div ebx ; quot in eax, rem in edx
    push edx ; store it for later
    inc ecx
    cmp eax, 0
    jnz pushloop
 poploop:
    pop eax ; get digit back
    add al, '0' ; convert to character
    mov Acc, eax
    invoke StdOut, addr Acc
    loop poploop
    ret

    invoke ExitProcess, 0

end start
0
Reply smarf 4/24/2009 8:46:56 PM

smarf wrote:
> Using masm32 on windows vista.
> It prints the correct result,720 and then a bunch of gibberish.
> I should delimit the string with ~ I think but I'm not sure and not
> sure how to do it.

Zero - the number 0, not the character '0'.

> Also shouldn't it just stop printing after 3 chars?

It should.

> I preferrably want to move everything into a buffer and print it at
> once instead.

A better bet.

> Using edi I guess?

Yeah, edi would be good - any register would do...

> I have really tried to get this working but googling does give
> anything.
> 
> 
> 
> 
> ;
> #########################################################################
> 
>       .386
>       .model flat, stdcall
>       option casemap :none
> 
> ;
> #########################################################################
> 
>     include \masm32\include\windows.inc
>     include \masm32\include\user32.inc
>     include \masm32\include\kernel32.inc
>     include \masm32\include\masm32.inc
> 
>     includelib \masm32\lib\user32.lib
>     includelib \masm32\lib\kernel32.lib
>     includelib \masm32\lib\masm32.lib
> 
> ;
> #########################################################################
> 
> .data
>     N sdword 6
>     Acc sdword 0
>     ;IntArray        dword 8 dup (?)
> 
> .code
> start:
>     mov ecx, N
>     mov eax, 1
> _fac:
>     mul ecx
>     loop _fac
> 
> 
>  utoa:
>     mov ebx, 10 ; we'll divide by this
>     xor ecx, ecx ; use as digit-counter
>  pushloop:
>     xor edx, edx
>     div ebx ; quot in eax, rem in edx
>     push edx ; store it for later
>     inc ecx
>     cmp eax, 0
>     jnz pushloop
>  poploop:
>     pop eax ; get digit back
>     add al, '0' ; convert to character
>     mov Acc, eax
>     invoke StdOut, addr Acc

The "Intel ABI" requires that we preserve certain registers, ebx, esi, 
edi, ebp across a call. It give us the same courtesy. Note that ecx is 
not on the "preserve" list! This implies that "invoke StdOut" (???) is 
allowed to trash ecx. I strongly suspect that your loopcount in ecx is 
being modified in the call. Try:

push ecx
invoke ...
pop ecx

And see if that helps. If it does, you'll probably want to use a 
different register - one that *is* preserved (we're done with ebx, at 
this point...)

      jnz pushloop
      mov ebx, ecx
poploop:
      pop eax ; get digit back
      add al, '0' ; convert to character
      mov Acc, eax
      invoke StdOut, addr Acc
      dec ebx
      jnz poploop

>     loop poploop
>     ret

Since you haven't "call"ed utoa, you probably don't want this "ret". You 
can exit a Windows program with "ret", I think - if you've followed the 
rules (preserved ebx, which we haven't) - but ExitProcess is better... 
and you can't do both :)

>     invoke ExitProcess, 0
> 
> end start

I'm not able to test this, but that's what "looks suspicious" to me...

Best,
Frank
0
Reply Frank 4/24/2009 9:11:58 PM


smarf <haskellian@gmail.com> wrote:
>
>Using masm32 on windows vista.
>It prints the correct result,720 and then a bunch of gibberish.
>I should delimit the string with ~ I think but I'm not sure and not
>sure how to do it.
>Also shouldn't it just stop printing after 3 chars?
>I preferrably want to move everything into a buffer and print it at
>once instead.
>Using edi I guess?
>I have really tried to get this working but googling does give
>anything.
>...
>
> poploop:
>    pop eax ; get digit back
>    add al, '0' ; convert to character
>    mov Acc, eax
>    invoke StdOut, addr Acc
>    loop poploop
>    ret

The biggest problem here is that you assume that ecx (which contains your
loop counter) survives the call to StdOut.  There is no such guarantee.
Only ebx, esi, edi, and ebp have guarantees.  So, ecx returns garbage, and
it continues printing.  You should add "push ecx" and "pop ecx" around the
invoke.
-- 
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
0
Reply Tim 4/25/2009 2:19:53 PM

2 Replies
199 Views

(page loaded in 0.055 seconds)

Similiar Articles:













7/15/2012 11:30:51 PM


Reply: