assemblyx86calling-conventionmasm32stdcall

Assembly: ecx not decreasing


I am using MASM and currently implementing a loop displaying Capital alphabets, small alphabets and ASCII in between

.386

.model flat, stdcall
option casemap :none

include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\masm32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\masm32.lib 

.data
    _ret sdword 13
    _car sdword 10
    _num sdword 0


.code
main:
    mov edx, 'A'
    mov ecx, 58
    jmp _end

_loop:  
    push edx
    invoke StdOut, esp
    invoke StdOut, addr _ret
    invoke StdOut, addr _car
    pop edx

    inc edx
    dec ecx

_end:
    cmp ecx, 0
    jne _loop

_exit:    
    invoke ExitProcess, 0
end main

The problem here I am facing is that ECX is not decreasing during the body of the loop and the loop continue forever even after A-Z %somehere% a-z


Solution

  • Your issue is one of calling convention. You've set the default convention to .model flat, stdcall which is not an issue. This means that unless otherwise specified stdcall calling convention will be used by the invoke directive. The stdcall calling convention includes these rules:

    1. The volatile registers are: EAX, ECX, EDX, and ST0 - ST7
    2. The non-volatile registers are: EBX, EBP, ESP, EDI, ESI, CS, DS, ES, FS and GS

    This means that you can't assume that the values in EAX, ECX, and EDX will remain the same after a call/invoke. Your loop variable is ECX so it is likely the calls to StdOut clobbered ECX each time they were called leading to the infinite loop.

    The best choice is to use one of the non-volatile registers EBX, EDI, ESI (you cause other issues if you use EBP and ESP). If you run out of registers you can: