I have an assignment for class that has us creating a CreateRandomString proc that will create strings of differing values and each time will store them in arrayString. Then in main proc a writeLoop will iterate through each string for a total of 20 strings 20 different times. Each string is to be of random length and random content but all must be capital letters. My program works succesfully except for the fact that the arrayString does not get properly reset due to the global nature of a lot of the things i'm using. I'm sure I could utilize the stack in some way but I am not quite sure how. Could one somehow push some cleared version of the array and then pop it when it needs to generate a new string? I am truly at a loss on what I am missing here. I am quite new to assembly and am all for any advice or pointers anyone has on this issue or a better way to approach the problem. I also want to note I utilized a proc from the Irvine32 library called RandomRange which just took the EAX value of 100 and rolls a random value from 0-(100-1).
;.386
;.model flat,stdcall
;.stack 4096
;ExitProcess proto,dwExitCode:dword
INCLUDE Irvine32.inc
.data
arrayString BYTE 100 DUP (?)
mainLoopCounter DWORD 20
.code
CreateRandomString proc
mov ESI, OFFSET arrayString
mov ECX, EAX ;Length of string
storeLoop:
mov EAX, 26
call RandomRange
add EAX, 65
mov BYTE PTR [ESI], AL
inc esi
loop storeLoop
call CRLF
ret
CreateRandomString endp
main proc
call Randomize
mainL:
mov EAX, 100
call RandomRange
call CreateRandomString
mov ESI, OFFSET arrayString
mov ECX, LENGTHOF arrayString
writeLoop:
mov AL, BYTE PTR [ESI]
call WriteChar
inc ESI
loop writeLoop
mov ECX, mainLoopCounter
dec mainLoopCounter
loop mainL
Invoke ExitProcess,0
main endp
end main
As far as methods I have attempted to solve the problem, I have been tampering with the stack because it is the one method we've learned for restoring things to their original values. Since ECX and ESI were being tampered with in other parts of the program, for the beginning of my storeLoop I did push ESI and push ECX and then popped them in their respective orders after storeLoop ended to no avail at all. I think this is because ESI is really just an address to store the char thats generated and is incremented and changing constantly, and ECX does not matter all that much in the context given. I need each string to be of random content, random length instead of just building on the previous until it crashes.
mov ESI, OFFSET arrayString mov ECX, LENGTHOF arrayString writeLoop:
Don't initialize the counter with LENGTHOF arrayString
. You need to setup ECX with the same number that you gave to CreateRandomString:
mov EAX, 100
call RandomRange ; -> EAX
push eax ; (1)
call CreateRandomString
pop ecx ; (1)
mov ESI, OFFSET arrayString
writeLoop:
Your RandomRange can return in EAX a number from 0 to 99. The CreateRandomString procedure will not function correctly when fed with a zero! Best never pass a zero to this proc:
Redo:
mov EAX, 100
call RandomRange ; -> EAX
test eax, eax
jz ReDo
push eax ; (1) [1,99]
call CreateRandomString
pop ecx ; (1)
mov ESI, OFFSET arrayString
writeLoop:
loop
instruction all the time!mov ECX, mainLoopCounter dec mainLoopCounter loop mainL
This can be written simpler and will execute faster:
dec mainLoopCounter
jnz mainL