I need to create a procedure that generates a random string of length L, containing all capital letters. When calling the procedure, I need to pass the value of L in EAX, and pass a pointer to an array of byte that will hold the random string. Then I need to write a test program that calls your procedure 20 times and displays the strings in the console window.
The code below wont work it comes back with these errors:
Line (33): error A2008: syntax error : main ENDP
Line (35): error A2144: cannot nest procedures
Line (46): error A2008: syntax error : RandomString
Line (48): error A2144: cannot nest procedures
Line (59): warning A6001: no return from procedure
Line (66): fatal error A1010: unmatched block nesting
I am still very new with Assembly Language...Any ideas on what I'm doing wrong and how to fix these errors? Thank you.
;Random Strings.
INCLUDE Irvine32.inc
TAB = 9 ;ASCII code for Tab
strLen=10 ;length of the string
.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
.data
str1 BYTE"The 20 random strings are:", 0
arr1 BYTE strLen DUP(?)
.code
main PROC
mov ed x, OFFSET str1 ;"The c20 random strings are:"
call WriteString ;Writes string
call Crlf ;Writes an end-of-line sequence to the console window.
mov ecx,20 ;Create 20 strings
L1: mov esi,OFFSET arr1 ;ESI: array address
mov eax,strLen ;EAX: string length
call RandomString ;generates the random string
call Display
mov al,TAB
call WriteChar ;leaves a tab space
exit
main ENDP
RandomString PROC USES eax esi
mov ecx,eax ;ECX = string length
L1: mov eax, 26
call RandomRange
add eax,65 ;EAX gets ASCII value of a capital letter
mov arr1[esi],eax
inc esi
loop L1
RandomString EXDP
Display PROC USES eax esi ;Displays the generated random string
mov ecx,eax ;ECX=string length
L1: mov eax, arr1[esi] ;EAX = ASCII value
call WriteChar ;writes the letter
inc esi
loop L1
Display ENDP
call dumpregs
INVOKE ExitProcess,0
END main
The
ENDP
directive goes without label. And without typos. Yours don't work, so the nextPROC
directive opens nested procedure inside procedure, that's not legal in MASM.mov arr1[esi],eax
stores 4 bytes, not one (consider what happens when you are at last 3 letters and buffer is only 10 bytes long).The
ENDP
is only MASM directive, not instruction, so yourRandomString
code will continue executing something after theloop
instruction, whatever happens to be in the following memory. You probably may be interested intoret
instruction. And check alsoDisplay
subroutine.RandomString
usesesi
as input argument, where you set the address of target buffer. Then it doesmov arr1[esi],...
, so it will doarr1+arr1
address calculation, resulting very likely into invalid memory access (or silent memory overwrite somewhere, but definitely not in your buffer).mov [esi],...
is enough, if it already contains pointer to buffer.Display
usesesi
, but you don't set it ahead ofcall Display
, so it will find inesi
whatever theRandomString
left there. And it does againarr1[esi]
, i.e.arr1+esi
address calculation."EAX = ASCII value" ... I would highly doubt that, as ASCII values need only 8 bits, and you load 32 bits from memory. The
eax
at that point will very likely contain 4 characters. ButWriteChar
will use only the bottom 8 bits ofeax
, so it will work as expected, but it's still sort of bug, showing your misunderstanding/ignorance of native CPU data types/registers.there are multiple
L1
labels, I thought they are global in MASM (but maybePROC
will localize them). Overall if will tell you I have in my code labelL1
, what does it say to you about what is it used for? How about if I renamed it toAlienInvasionV4_HandlerOfMultidimensionalTeleportationError:
, can you guess anything about its function even without seeing the code? What the point in using something cryptic like "L1"?there's no loop in
main
.RandomString
will changeecx
(even if there would be loop inmain
, it will not work as expected).Display
will try to use alsoeax
value as input, but you don't set it ahead ofcall Display
.... maybe some more bugs, but I got tired of reading through it (I don't have windows+irvine lib to actually run it, so all my notes are just by proofreading your source and running it in head... imagine you could read it after yourself too and reason about each instruction, whoa!) ... you should have been able to find+fix most of these on your own, not sure what you are asking here on SO. It will get lot more tedious than fixing few syntax errors with wrongly used
ENDP
. Although your code has glimpse of algorithmic sanity, doesn't feel completely clueless like you don't understand CPU at all (except you missed the "super global" nature of registers and expect them to keep their values over calls), more like lack of precision and experience. You will need lot more precision with ASM, the machine will happily execute any legal instruction you throw at it, without any warning about consequences.