I have this code here which is supposed to fill an array with the digits that the user enters and then print them, but I'm new to masm32 and its giving me a lot of trouble, its getting into somekind of infinite loop and not printing anything that I enter into the array..
.386
.model flat,stdcall
option casemap :none
include\masm32\include\windows.inc
include\masm32\include\kernel32.inc
include\masm32\include\masm32.inc
include\masm32\include\user32.inc
includelib\masm32\lib\kernel32.lib
includelib\masm32\lib\masm32.lib
includelib\masm32\lib\user32.lib
.data
MsgNum db "Insert amount of digits -> ", 0
MsgDigit db "Inserte digit -> ", 0
.data?
numDigit db 2 dup (?)
digits dword 36 dup (?)
digit db 2 dup (?)
.code
start:
invoke StdOut, addr MsgNum
invoke StdIn, addr numDigit , 10
invoke atodw, addr numDigit
mov ebx, eax
mov edx, 0
get:
push edx
invoke StdOut, addr MsgDigit
invoke StdIn, offset digit, 10
invoke atodw, offset digit
mov digits[edx*4], eax
pop edx
inc edx
cmp edx, ebx
jne get
mov ecx, 0
prnt:
push ecx
mov ebx, digits[ecx*4]
invoke dwtoa, ebx,addr digit
invoke StdOut, addr digit
pop ecx
inc ecx
cmp edx, ecx
jne prnt
invoke ExitProcess, 0
Im probably doing something really stupid but Im having a hard time trying to figure out what exactly
The buffers are to small - the StdIn function internally use ReadFile with the specified buffer size. The problem is that the line break is not correctly removed from the input stream, if the buffer is to small (for window a line break consist of two bytes: CR,LF == 13,10) - this cause garbage input for further reads.
For the first loop, EDX is used before it has been recovered from the stack. The second loop overwrites EBX that holds the requested digit count.
include \masm32\include\masm32rt.inc ; <- does default setup
.const
szMsgNum db "Insert amount of digits -> ", 0
szMsgDigit db "Inserte digit -> ", 0
.code
main proc ; advantage of using a PROC: local variables + the labels "get" and "prnt" are not global
LOCAL szNumDigits[128]:BYTE ; generously buffer size!
LOCAL szDigit[128]:BYTE ;
LOCAL digits[36]:ptr BYTE
invoke StdOut, offset szMsgNum
invoke StdIn, addr szNumDigits, LENGTHOF szNumDigits
invoke atodw, addr szNumDigits
mov ebx, eax
xor edx,edx ;mov edx, 0 ; using esi or edi would saves the PUSH/POP pair
get:
push edx
invoke StdOut, offset szMsgDigit
invoke StdIn, addr szDigit, LENGTHOF szDigit
invoke atodw, addr szDigit
pop edx ; <-------
mov digits[edx*4],eax
inc edx
cmp edx, ebx
jne get
xor ecx,ecx ; mov ecx,0
prnt:
push ecx
mov edx, digits[ecx*4] ; <------
invoke dwtoa, edx,addr szDigit
invoke StdOut, addr szDigit
pop ecx
inc ecx
cmp ecx,ebx
jne prnt
invoke ExitProcess, 0
main endp
end main
the buffers should be 256 bytes, as i recently learned - lol
watch the pointers and counters
EAX, ECX, and EDX are likely to be trashed when calling other routines
also - you were missing "end start" - the end directive should reference the entry point
otherwise, pretty good for a newbie :t
.386
.model flat,stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\user32.lib
.data
MsgNum db "Insert amount of digits -> ", 0
MsgDigit db "Inserte digit -> ", 0
.data?
numDigit db 256 dup (?)
digits dword 36 dup (?)
digit db 256 dup (?)
.code
start:
invoke StdOut, addr MsgNum
invoke StdIn, addr numDigit , 256
invoke atodw, addr numDigit
mov ebx, eax
mov edx, 0
get:
push edx
invoke StdOut, addr MsgDigit
invoke StdIn, offset digit, 256
invoke atodw, offset digit
pop edx
mov digits[edx*4], eax
inc edx
cmp edx, ebx
jne get
mov ecx, 0
prnt:
push ecx
push edx
mov ebx, digits[ecx*4]
invoke dwtoa, ebx,addr digit
invoke StdOut, addr digit
pop edx
pop ecx
inc ecx
cmp edx, ecx
jne prnt
invoke ExitProcess, 0
end start
Wow thanks for the help, I see what you guys are saying.. Reading the code "qWord" posted I see he wrote that esi or edi would save the push/pop bit, didnt know that, gonna have to read a bit more about asm hahaha thanks
that's not really dictated by asm, per se
it's called the "Windows ABI" (Application Binary Interface)
it says that EBX, EBP, ESI, and EDI are preserved across function calls
EAX, ECX, and EDX may be trashed, and are often used to return results (specifically, EAX)
the direction flag should remain cleared (up direction) before calling a function
we generally write our subroutines to follow the same set of rules
that way, they can be used anywhere an API function can be