Jachdich
Jachdich

Reputation: 792

Assembly loops loop too many times

I am very new to assembly (Started learning yesterday) and have a problem with loops:

The code below should print the values 0-49, but instead it prints 0-49 and then ~20 lines of rubbish (I'm assuming this is part of the stack that other programs/other bits of the program are using). I expect the problem is the second loop, .loop, as it's printing the wrong number of lines, and printing is handled by .loop.

I am using the FASM (Flat Assembler) program to compile this.

Code:

format PE console
include "win32ax.inc"
start:
    mov ecx, 50 ;number of loops
    .mainloop: ;for testing purposes, just pushes 49-0 onto the stack
        push ecx ;push onto stack
        dec ecx ;decrement counter
        jnz .mainloop ;jump if counter not zero

    mov ecx, 50 ;reset ecx (counter)
    .loop: ;prints the stack, should print 0-49 but also prints garbage at the end
        pop eax ;pop from stack to eax
        cinvoke printf,formatstring,eax ;print eax
        dec ecx ;decrement counter
        jnz .loop ;loop if counter not zero
    int 15;wait 5 seconds ish
    invoke ExitProcess ;exit

formatstring    db "%d",13,10,0 ;to print digits instead of ASCII chars

section '.idata' import data readable ;stuff I copied but seems to work
    library msvcrt,'msvcrt.dll',\ ;don't understand it
        kernel32,'kernel32.dll'   ;^
    import  msvcrt,printf,'printf';^^
    import  kernel32,ExitProcess,"ExitProcess";^^^

Thanks in advance.

p.s. How do I format the code with syntax highlighting?

Upvotes: 1

Views: 319

Answers (2)

melpomene
melpomene

Reputation: 85867

ecx is one of the "caller-saved" registers, meaning any function call can modify ecx and it is the caller's job to save/restore it where necessary.

See also:

According to the Intel ABI to which the vast majority of compilers conform, the EAX, EDX, and ECX are to be free for use within a procedure or function, and need not be preserved.

Your call to printf in the loop likely clobbers ecx.

Upvotes: 2

Jachdich
Jachdich

Reputation: 792

The problem is that cinvoke printf,formatstring,eax changes the ECX register, as pointed out by zx485. It turns out it also changes the EDX register.

To fix it, I changed to using the EBX register, which is not modified by cinvoke printf,formatstring,eax.

I hope this helps someone.

EDIT: melpomene posted a much better answer.

Upvotes: 3

Related Questions