Search code examples
assemblyasciimasm

x86 assembly print register ascii


I realize that there are a lot of questions/answers about how to output an integer in its decimal, ASCII form. I've taken some code and modified it for my own needs, but instead of just printing the number, it continues printing gibberish characters, and windows tells me the program stopped working. I think the problem is that it keeps popping values of the stack even though it should break out of the loop. Here is the full code:

.386
.model flat, stdcall
option casemap :none

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

.data
base dd 10
ans dd ?

.code
start:
MOV ECX,3    ;I'm writing a compiler using
PUSH ECX     ;Jack Crenshaw's "Let's Build A Compiler!"
MOV ECX,9    ;This is just some sample output that I put in
ADD ECX,[ESP];The answer that prints out should be 42
PUSH ECX
MOV ECX,2
XOR EDX,EDX
POP EAX
IDIV ECX
MOV ECX,EAX
PUSH ECX
MOV ECX,7
IMUL ECX,[ESP]

mov eax,ecx
xor ecx,ecx
separateDigit: 
xor edx,edx
idiv base
push edx
inc ecx
cmp eax,0
jne separateDigit

printDigit: 
mov ans,0
pop ans
dec ecx
add ans,'0'
invoke StdOut,addr ans
cmp ecx,0
jne printDigit

invoke ExitProcess, 0
end start

Can someone who hasn't been staring at it for hours chime in and tell me what I'm doing wrong?


Solution

  • The invoke call is probably not "register safe" so you need to preserve your ecx value:

    printDigit: 
        mov ans,0
        pop ans
        dec ecx
        add ans,'0'
        push ecx     ; save ecx
        invoke StdOut,addr ans
        pop ecx      ; restore ecx
        cmp ecx,0
        jne printDigit