The following program is supposed to randomly generate 3 sets of numbers in a specified range and print them out.
I get stuck in an infinite loop for some reason 'but' it appears to be working in one aspect I was SURE it would fail and that is the use of a negative number.
on line 33 I put -5 into eax. This should crash of spit out a horrible number because it is not signed. I would surely think that I would have to do twos-compliment in some manner.
How do I fix the loop and how did I screw up in reverse?
***************************************code**********************************
TITLE Program to generate random numbers (random1.asm)
INCLUDE Irvine32.inc
COUNT = 10
.data
commaStr BYTE ", ",0
.code
main PROC
call Clrscr
call Randomize ; random generator
mov ecx,COUNT ; loop counter
L1: mov eax,8 ; generate rand int (0..8)
call RandomRange
sub eax,0 ; 0 range
call WriteInt ; display the integer
mov edx,OFFSET commaStr
call WriteString
loop L1
L2: mov eax,92 ; generate rand int (25..92)
call RandomRange
sub eax,25
call WriteInt ; display the integer
mov edx,OFFSET commaStr
call WriteString
loop L2
L3: mov eax,-5 ; generate rand int (-5..6) ???There is no way this should work!!!!?????
call RandomRange
sub eax,6
call WriteInt
mov edx,OFFSET commaStr
call WriteString
loop L3
call Crlf
exit
main ENDP
END main
*******************************************end code****************************
mov ecx,COUNT ; loop counter
L1:
;some code
loop L1
the above code passes through the loop 10 times (COUNT = 10)
after each pass, ECX is one less
when the loop is complete, ECX = 0
at that point, it passes to the next loop...
L2:
;some more code
loop L2
the problem here is, the loop starts with a value in ECX of 0
loop still works, but it treats that 0 like 4,294,967,296, because it will again decrement ECX until it is 0
so, you need to initialize the loop count register (ECX) at the beginning of each loop
mov ecx,COUNT ; loop counter
L1:
;
loop L1
mov ecx,COUNT ; loop counter
L2:
;
loop L2
mov ecx,COUNT ; loop counter
L3:
;
loop L3
or
mov ecx,COUNT ; loop counter
push ecx
L1:
;
loop L1
pop ecx
push ecx
L2:
;
loop L2
pop ecx
L3:
;
loop L3
And even the first loop could run indefinitely depending on how the ECX is used in the RandomRange, WriteInt and Write String procedures.
The "-5" gets treated as a value of 4,294,967,291 by the assembler and would not raise any exception. It may also be treated in the same manner by the RandomRange procedure; without access to it, it's impossible to tell.
Ray,
most of Kip's library functions preserve all registers (except EAX), so he is safe, there :P
in fact, he could put OFFSET commaStr in EDX at the beginning and remove that from the loops
it will be there all the way through - lol
and, you are right about the negative value - it is treated as unsigned
When calculating random numbers in a specified range, subtract the low bound from the high bound, then generate the random number based on the difference, then add the low bound to the returned random number.
mov eax,8 ; Set the high.
sub eax,0 ; Less the low.
call RandomRange ; Get the random number.
add eax,0 ; Add the low (0 <= ran <= 8).
...
mov eax,92 ; Set the high.
sub eax,25 ; Less the low.
call RandomRange ; Get the random number.
add eax,25 ; Add the low (25 <= ran <= 92).
...
mov eax,10 ; Set the high (10).
sub eax,-50 ; Less the low (60).
call RandomRange ; Get the random number.
add eax,-50 ; Add the low (-50 <= ran <= 10).
Dave (a different Dave - KeepingRealBusy)
BWUUUUUUUUUUUUUUUUUUUHahahahahahaha
Can you check this code?
I am guessing it is working because it is sending my avg antivirus going nuts.
It says it's a threat???
Stoopid AVG.
But I cannot even run the file.
My antivirus locks it at first attempt..
*******************************new Code**************************
TITLE Program to generate random numbers (random1.asm)
INCLUDE Irvine32.inc
COUNT = 10
.data
commaStr BYTE ", ",0
.code
main PROC
call Clrscr
call Randomize ; random generator
mov ecx,COUNT ; loop counter
L1: mov eax,8 ; generate rand int (0..8)
sub eax,0 ; 0 range
call RandomRange
add eax,0
call WriteInt ; display the integer
mov edx,OFFSET commaStr
call WriteString
loop L1
mov ecx,COUNT ; loop counter
L2: mov eax,92 ; generate rand int (25..92)
sub eax,25
call RandomRange
add eax,25
call WriteInt ; display the integer
mov edx,OFFSET commaStr
call WriteString
loop L2
mov ecx,COUNT ; loop counter
L3: mov eax,6 ; generate rand int (-5..6) ???There is no way this should work!!!!?????
sub eax,-5
call RandomRange
add eax,-5
call WriteInt
mov edx,OFFSET commaStr
call WriteString
loop L3
call Crlf
exit
main ENDP
END main
**********************end code*************************
Why would the antivirus flag this asm program?
step 1) remove AVG - it barks at assembly programs all the time - i use Malwarebyte's Anti-Malware
step 2) try this program :P
TITLE Random
;#########################################################
INCLUDE Irvine32.inc
;#########################################################
RandLoop PROTO :DWORD,:DWORD
;#########################################################
COUNT = 10
;#########################################################
.DATA
commaStr BYTE ", ",0
;#########################################################
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD
LOCAL dwRange:DWORD
mov eax,dwMaxVal
sub eax,dwMinVal
mov dwRange,eax
mov edx,OFFSET commaStr
mov ecx,COUNT
RLoop0: mov eax,dwRange ; generate rand int
call RandomRange
add eax,dwMinVal
call WriteInt ; display the integer
call WriteString
loop RLoop0
ret
RandLoop ENDP
;*********************************************************
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8
INVOKE RandLoop,25,92
INVOKE RandLoop,-5,6
call Crlf
exit
main ENDP
;#########################################################
END main
A small list of questions.
So nice to see clean code with some thought behind it.
Questions are commented in the code!!
TITLE Random
INCLUDE Irvine32.inc
RandLoop PROTO :DWORD,:DWORD
;#########################################################
COUNT = 10
;#########################################################
.DATA
commaStr BYTE ", ",0
;#########################################################
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD
LOCAL dwRange:DWORD
mov eax,dwMaxVal ;you are loading the registers to prepare for the value here?
sub eax,dwMinVal ;you are loading the registers to prepare for the value here?
mov dwRange,eax ;I am confuse because I am not used to seeing more than one thing in a register at a time?
mov edx,OFFSET commaStr
mov ecx,COUNT
RLoop0: mov eax,dwRange ; generate rand int
call RandomRange
add eax,dwMinVal
call WriteInt ; display the integer
call WriteString
loop RLoop0
ret
RandLoop ENDP
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8 ;The use of INVOKE here is incremental from RandLoop? Grabs this one first,
INVOKE RandLoop,25,92 ;Then this one second
INVOKE RandLoop,-5,6 ;and this one last. No more INVOKEs so the loop terminates?
call Crlf
exit
main ENDP
;#########################################################
END main
in this code, i calculate the range and store it in a local variable
that way, we don't repeat the same steps in each pass of the loop
notice that the Range = MaxVal - MinVal
1) load EAX with the MaxVal
2) subtract MinVal, now EAX = Range
3) store Range in the local variable named dwRange
mov eax,dwMaxVal ;you are loading the registers to prepare for the value here?
sub eax,dwMinVal ;you are loading the registers to prepare for the value here?
mov dwRange,eax ;I am confuse because I am not used to seeing more than one thing in a register at a time?
INVOKE is like CALL
INVOKE RandLoop,0,8 generates the following code
push 8
push 0
call RandLoop
then, the PROC directive for RandLoop tells the routine how to find the parameters on the stack
INVOKE RandLoop,0,8 ;The use of INVOKE here is incremental from RandLoop? Grabs this one first,
INVOKE RandLoop,25,92 ;Then this one second
INVOKE RandLoop,-5,6 ;and this one last. No more INVOKEs so the loop terminates?
the loop code is inside the RandLoop proc
you can place any two values on the INVOKE line and it will do the same thing using those values as min and max
if you want to see just one call, comment out the other two INVOKE's
that may help you get a better understanding for how it works
; INVOKE RandLoop,0,8
INVOKE RandLoop,25,92
; INVOKE RandLoop,-5,6
oh - did the program work correctly ?
YES YOU DID SIR!
:)
And now I am tinkering a little bit more.
I put in a second loop. I am trying to now do a random column down, actually a pair and then add them.
I am getting some crazy numbers and I am following your rule to plug them into a variable.
I am missing something..?
TITLE Random
INCLUDE Irvine32.inc
RandLoop PROTO :DWORD,:DWORD
RandLoop2 PROTO :DWORD,:DWORD
;#########################################################
COUNT = 10
;#########################################################
.DATA
commaStr BYTE ", ",0
str1 BYTE "Total= ",0
;#########################################################
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD
LOCAL dwRange:DWORD
mov eax,dwMaxVal
sub eax,dwMinVal
mov dwRange,eax
mov edx,OFFSET commaStr
mov ecx,COUNT
RLoop0: mov eax,dwRange ; generate rand int
call RandomRange
add eax,dwMinVal
call WriteInt ; display the integer
call WriteString
loop RLoop0
ret
RandLoop ENDP
;second loop begins here to count to random colums down
RandLoop2 PROC dwMinVal2:DWORD,dwMaxVal2:DWORD
LOCAL dwRange2:DWORD,dwRange3:DWORD
mov eax,dwMaxVal2
sub eax,dwMinVal2
mov dwRange2,eax
mov edx,OFFSET commaStr
mov ecx,COUNT
RLoop1: mov eax,dwRange2 ; generate rand int
call RandomRange
add eax,dwMinVal2
call WriteInt ; display the integer
call WriteString
;My problem starts right here. I want to produce a second colum and then add the first
;two colums and produce thier total in a third.
mov eax,dwRange3 ; generate rand int
call RandomRange
add eax,dwMinVal2
call WriteInt ; display the integer
call WriteString
add eax,dwRange3
call WriteInt ; display the integer
call WriteString
;anything I put here to do a basic math function of adding eax and ebx together fails miserably??
call Crlf
loop RLoop1
ret
RandLoop2 ENDP
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8
INVOKE RandLoop,25,92
INVOKE RandLoop,-5,6
INVOKE RandLoop2,1,6
call Crlf
exit
main ENDP
;#########################################################
END main
TITLE Random
INCLUDE Irvine32.inc
RandLoop PROTO :DWORD,:DWORD,:DWORD
.DATA
str1 BYTE "Total= ",0
commaStr BYTE ", ",0
show_sum byte "the sum is: ",0
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD,COLUMN:DWORD
;this function show in screen some random number in columns
;return in eax the sum of these numbers
LOCAL dwRange:DWORD
LOCAL VALUE_FINAL:DWORD
mov VALUE_FINAL,0 ;we initialize this variable with zero
cmp COLUMN,0 ;zero columns?
JE DO_NOTHING ;so do nothing
mov eax,dwMaxVal
sub eax,dwMinVal
mov dwRange,eax
mov edx,OFFSET commaStr
mov ecx,COLUMN
RLoop0:
mov eax,dwRange
call RandomRange
add eax,dwMinVal
add [VALUE_FINAL],eax ;first moment the value_final is zero, second moment is ????????
call WriteInt
call WriteString
loop RLoop0
mov eax,VALUE_FINAL ;and after we show the sum of the numbers
DO_NOTHING:
ret
RandLoop ENDP
main PROC
call Clrscr
call Randomize
INVOKE RandLoop,0,8,0 ;0 columns, so don't do nothing
call Crlf
INVOKE RandLoop,0,8,1 ;1 colum
call Crlf
INVOKE RandLoop,25,92,4 ;4 columns
push eax ;we save the returned value
mov edx,offset show_sum
call WriteString
pop eax ;now, we get it back
call WriteInt
call Crlf
INVOKE RandLoop,-5,6,8 ;8 columns
call Crlf
exit
main ENDP
END main
TITLE Random
INCLUDE Irvine32.inc
RandLoop PROTO :DWORD,:DWORD,:DWORD
.DATA
str1 BYTE "Total= ",0
commaStr BYTE ", ",0
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD,COLUMN:DWORD
;this procedure show X columns of random value betwen dwMinVal and dwMaxVal
;this procedure add one colum to show the sum of values
LOCAL dwRange:DWORD
LOCAL VALUE_FINAL:DWORD
mov VALUE_FINAL,0 ;we initialize this variable with zero
cmp COLUMN,0 ;zero columns?
JE DO_NOTHING ;so do nothing
mov eax,dwMaxVal
sub eax,dwMinVal
mov dwRange,eax
mov edx,OFFSET commaStr
mov ecx,COLUMN
RLoop0:
mov eax,dwRange
call RandomRange
add eax,dwMinVal
add [VALUE_FINAL],eax ;first moment the value_final is zero, second moment is ????????
call WriteInt
call WriteString
loop RLoop0
mov edx, offset str1 ;we show the "total= "
call WriteString
mov eax,VALUE_FINAL ;and after we show the sum of the numbers
call WriteInt
call Crlf ;an enter in the end of column
DO_NOTHING:
ret
RandLoop ENDP
main PROC
call Clrscr
call Randomize
INVOKE RandLoop,0,8,0 ;0 columns, so do not show
INVOKE RandLoop,0,8,1 ;1 colum
INVOKE RandLoop,25,92,4 ;4 columns
INVOKE RandLoop,-5,6,8 ;8 columns
exit
main ENDP
END main
try these two bcddd214, you are make good progress, keep walking.
I have seen your procedure, and you forgot some thing:
mov eax,dwRange3 ;in this line, you forgot to start the dwRange3 variable
SOOOOO CLOSE!!!!
My RLoop1 does not seem to want to kick out at the end of adding '2'/'two' numbers.
It wants to add up all the way to the end?
***********************************************
TITLE Random
INCLUDE Irvine32.inc
RandLoop PROTO :DWORD,:DWORD
RandLoop2 PROTO :DWORD,:DWORD,:DWORD
;#########################################################
COUNT = 10
;#########################################################
.DATA
commaStr BYTE ", ",0
str1 BYTE "Total= ",0
;#########################################################
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD
LOCAL dwRange:DWORD
mov eax,dwMaxVal ;you are loading the registers to prepare for the value here?
sub eax,dwMinVal ;you are loading the registers to prepare for the value here?
mov dwRange,eax ;I am confuse because I am not used to seeing more than one thing in a register at a time?
mov edx,OFFSET commaStr
mov ecx,COUNT
RLoop0: mov eax,dwRange ; generate rand int
call RandomRange
add eax,dwMinVal
call WriteInt ; display the integer
call WriteString
loop RLoop0
call Crlf
call Crlf
ret
RandLoop ENDP
;second loop begins here to count to random colums down
RandLoop2 PROC dwMinVal2:DWORD,dwMaxVal2:DWORD,COLUMN:DWORD
LOCAL dwRange2:DWORD,VALUE_FINAL:DWORD
mov VALUE_FINAL,0 ;we initialize this variable with zero
cmp COLUMN,0 ;zero columns?
JE DO_NOTHING ;so do nothing
mov eax,dwMaxVal2
sub eax,dwMinVal2
mov dwRange2,eax
mov edx,OFFSET commaStr
mov ecx,COLUMN
RLoop1: ;This loop is suppoed to add 2 random numbers side by side and display total next to it THEN return to next line???
mov eax,dwRange2 ; generate rand int
call RandomRange
add eax,dwMinVal2
add [VALUE_FINAL],eax
call WriteInt ; display the integer
call WriteString
;when INVOKE runs out, it will exit the loop
loop RLoop1
mov edx, offset str1 ;we show the "total= "
call WriteString
mov eax,VALUE_FINAL ;and after we show the sum of the numbers
call WriteInt
call Crlf ;an enter in the end of column
DO_NOTHING:
ret
RandLoop2 ENDP
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8 ;The use of INVOKE here is incremental from RandLoop? Grabs this one first,
INVOKE RandLoop,25,92 ;Then this one second
INVOKE RandLoop,-5,6 ;and this one last. No more INVOKEs so the loop terminates?
INVOKE RandLoop2,1,6,8
call Crlf
exit
main ENDP
;#########################################################
END main
I am discovering the hard way that INVOKE directly correlates with the number of dword variables declared in PROC?
on line 86, INVOKE declares RandLoop2 with 3 digits. The third one does not need to be there?
The program almost craps at assemble time as is. I am close, but still missing something
*************************************************************
TITLE Random
INCLUDE Irvine32.inc
RandLoop PROTO :DWORD,:DWORD
RandLoop2 PROTO :DWORD,:DWORD,:DWORD
;#########################################################
COUNT = 10
;#########################################################
.DATA
commaStr BYTE ", ",0
str1 BYTE "Total= ",0
;#########################################################
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD
LOCAL dwRange:DWORD
mov eax,dwMaxVal ;you are loading the registers to prepare for the value here?
sub eax,dwMinVal ;you are loading the registers to prepare for the value here?
mov dwRange,eax ;I am confuse because I am not used to seeing more than one thing in a register at a time?
mov edx,OFFSET commaStr
mov ecx,COUNT
RLoop0: mov eax,dwRange ; generate rand int
call RandomRange
add eax,dwMinVal
call WriteInt ; display the integer
call WriteString
loop RLoop0
call Crlf
call Crlf
ret
RandLoop ENDP
;second loop begins here to count to random colums down
RandLoop2 PROC dwMinVal2:DWORD,dwMaxVal2:DWORD,COLUMN:DWORD
LOCAL dwRange2:DWORD,VALUE_FINAL:DWORD
mov VALUE_FINAL,0 ;we initialize this variable with zero
cmp COLUMN,0 ;zero columns?
JE DO_NOTHING ;so do nothing
mov eax,dwMaxVal2
sub eax,dwMinVal2
mov dwRange2,eax
mov edx,OFFSET commaStr
mov ecx,COLUMN
RLoop1:
mov eax,dwRange2 ; generate rand int
call RandomRange
call WriteInt
mov ebx,eax
; mov ebx,dwMinVal2
call RandomRange
call WriteInt
add eax,ebx
call DumpRegs
; add [VALUE_FINAL],eax
; call WriteInt ; display the integer
;when INVOKE runs out, it will exit the loop
mov edx, offset str1 ;we show the "total= "
; mov eax,VALUE_FINAL ;and after we show the sum of the numbers
call WriteString
; mov eax,VALUE_FINAL ;and after we show the sum of the numbers
call WriteInt
call Crlf ;an enter in the end of column
loop RLoop1
DO_NOTHING:
ret
RandLoop2 ENDP
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8 ;The use of INVOKE here is incremental from RandLoop? Grabs this one first,
INVOKE RandLoop,25,92 ;Then this one second
INVOKE RandLoop,-5,6 ;and this one last. No more INVOKEs so the loop terminates?
INVOKE RandLoop2,1,6,9
call Crlf
exit
main ENDP
;#########################################################
END main
i think what you really want in RandLoop2 is to add another local variable, not another parameter on the PROC line
parameters are passed to the routine by the INVOKE
local variables are just temporary values stored internally by the routine
although, i am not really sure what you are trying to do with COLUMN :P
when i showed you what code was generated by the assembler for INVOKE, that was fairly simple
understanding the code that is generated to make the routine is a bit more complicated
i didn't want to throw that at you, yet, because i didn't want to confuse you
it may be best for you to learn a little more about registers, data, etc before delving into stack frames :P
EDIT - ok - i think i see what you were trying to do
you do want to pass another parameter
but, i don't understand the rest of the modifications to that routine
I think I figured it out.
I went back to what you had sent earlier and took a good long look at it.
1 question and one possible solution.
Question 1
It looks like I have this doing more or less what I want it to but I want to have it do 9 more lines like the last.
Just like the RandLoop.
Should I just turn everything from the PROC definition to the end of RandLoop2 as a procedure of RandLoop?
TITLE Random
INCLUDE Irvine32.inc
RandLoop PROTO :DWORD,:DWORD
RandLoop2 PROTO :DWORD,:DWORD,:DWORD
;#########################################################
COUNT = 10
COUNT2 = 2
;#########################################################
.DATA
commaStr BYTE ", ",0
str1 BYTE "Total= ",0
;#########################################################
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD
LOCAL dwRange:DWORD
mov eax,dwMaxVal ;you are loading the registers to prepare for the value here?
sub eax,dwMinVal ;you are loading the registers to prepare for the value here?
mov dwRange,eax ;I am confuse because I am not used to seeing more than one thing in a register at a time?
mov edx,OFFSET commaStr
mov ecx,COUNT
RLoop0: mov eax,dwRange ; generate rand int
call RandomRange
add eax,dwMinVal
call WriteInt ; display the integer
call WriteString
loop RLoop0
call Crlf
call Crlf
ret
RandLoop ENDP
;second loop begins here to count to random colums down
RandLoop2 PROC dwMinVal2:DWORD,dwMaxVal2:DWORD,COLUMN:DWORD
;this procedure show X columns of random value betwen dwMinVal and dwMaxVal
;this procedure add one colum to show the sum of values
LOCAL dwRange2:DWORD
LOCAL VALUE_FINAL:DWORD
mov VALUE_FINAL,0 ;we initialize this variable with zero
;cmp COLUMN,0 ;zero columns?
;mov COUNT2,0 ;set count2 to zero
JE DO_NOTHING ;so do nothing
mov eax,dwMaxVal2
sub eax,dwMinVal2
mov dwRange2,eax
mov edx,OFFSET commaStr
; mov ecx,COLUMN
mov ecx,COUNT2
RLoop1:
mov eax,dwRange2
call RandomRange
add eax,dwMinVal2
add [VALUE_FINAL],eax ;first moment the value_final is zero, second moment is ????????
call WriteInt
call WriteString
loop RLoop1
mov edx, offset str1 ;we show the "total= "
call WriteString
mov eax,VALUE_FINAL ;and after we show the sum of the numbers
call WriteInt
call Crlf ;an enter in the end of column
DO_NOTHING:
ret
RandLoop2 ENDP
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8 ;The use of INVOKE here is incremental from RandLoop? Grabs this one first,
INVOKE RandLoop,25,92 ;Then this one second
INVOKE RandLoop,-5,6 ;and this one last. No more INVOKEs so the loop terminates?
INVOKE RandLoop2,1,6,9
call Crlf
exit
main ENDP
;#########################################################
END main
i still don't know what you are going for
certainly, i would try to use the same code for both functions
there are a few ways to do that, depending on the situation
for example, i might write a RandLoop function that has 3 parameters
then, write another one that has only 2
inside that function, i would fill in the 3rd paramter and use the other two from the invoke
there is an important thing to understand, here
that is, the assembler generates exit code whenever you add a RET instruction
among other things, it uses a special form of RET that pops the parameters off the stack
so, a function that has 3 parameters will use a RET 12, and a function that has 2 parameters will use a RET 8
that means you can't "mix and match", or "nest" dissimilar functions
here is a little explanation of the assembler generated code...
http://www.masm32.com/board/index.php?topic=15307.msg124847#msg124847
and a little more involved one that shows how to write your own stack frame
http://www.masm32.com/board/index.php?topic=14381.msg114921#msg114921
I GOT IT!
working code!
:)
TITLE Random
INCLUDE Irvine32.inc
RandLoop PROTO :DWORD,:DWORD
RandLoop2 PROTO :DWORD,:DWORD,:DWORD
;#########################################################
COUNT = 10
COUNT2 = 2
;#########################################################
.DATA
commaStr BYTE ", ",0
str1 BYTE "Total= ",0
;#########################################################
.CODE
RandLoop PROC dwMinVal:DWORD,dwMaxVal:DWORD
LOCAL dwRange:DWORD
mov eax,dwMaxVal ;you are loading the registers to prepare for the value here?
sub eax,dwMinVal ;you are loading the registers to prepare for the value here?
mov dwRange,eax ;I am confuse because I am not used to seeing more than one thing in a register at a time?
mov edx,OFFSET commaStr
mov ecx,COUNT
; call DumpRegs
RLoop0: mov eax,dwRange ; generate rand int
call RandomRange
add eax,dwMinVal
call WriteInt ; display the integer
call WriteString
loop RLoop0
call Crlf
call Crlf
ret
RandLoop ENDP
;second loop begins here to count to random colums down
RandLoop2 PROC dwMinVal2:DWORD,dwMaxVal2:DWORD,COLUMN:DWORD
;this procedure show X columns of random value betwen dwMinVal and dwMaxVal
;this procedure add one colum to show the sum of values
LOCAL dwRange2:DWORD
LOCAL VALUE_FINAL:DWORD
mov VALUE_FINAL,0 ;we initialize this variable with zero
;cmp COLUMN,0 ;zero columns?
;mov COUNT2,0 ;set count2 to zero
JE DO_NOTHING ;so do nothing
mov eax,dwMaxVal2
sub eax,dwMinVal2
mov dwRange2,eax
mov edx,OFFSET commaStr
; mov ecx,COLUMN
mov ecx,COUNT2
RLoop1:
mov eax,dwRange2
call RandomRange
add eax,dwMinVal2
add [VALUE_FINAL],eax ;first moment the value_final is zero, second moment is ????????
call WriteInt
call WriteString
; call DumpRegs
loop RLoop1
mov edx, offset str1 ;we show the "total= "
call WriteString
mov eax,VALUE_FINAL ;and after we show the sum of the numbers
call WriteInt
call Crlf ;an enter in the end of column
DO_NOTHING:
ret
RandLoop2 ENDP
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8 ;The use of INVOKE here is incremental from RandLoop? Grabs this one first,
INVOKE RandLoop,25,92 ;Then this one second
INVOKE RandLoop,-5,6 ;and this one last. No more INVOKEs so the loop terminates?
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
INVOKE RandLoop2,1,6,0
call Crlf
exit
main ENDP
;#########################################################
END main
Hello bcddd214, when you are learning assembly you need follow some rules. This is not absolutely true, but when learning, this works.
1 - every "call" have a "ret". So if you call some procedure, inside that procedure have a ret.
2 - comment your code so much, put in the header of 'proc' a comment saying what that procedure does, what registers are modified, what that procedure returns, and what the procedures need to work.
3 - Local variables inside a proc are only seen inside that proc. Global variables are seen by all the program, they are stored in .data section. And equates (=) are constants.
4 - Don't think that the values in the registers are preserved, because you can do a call to some procedure and that procedure can modify some registers/flags.
So when you see a "call Crlf" remember that inside that procedure, have a ret to return to your code again.
When you see a "invoke Crlf" remember that inside that procedure have a ret to return to your code again.
You called(invoke) RandLoop2 10 times alright? So, you can rewrite it using loop:
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8 ;The use of INVOKE here is incremental from RandLoop? Grabs this one first,
;no, invoke is a call, nothing related with loop
INVOKE RandLoop,25,92 ;Then this one second
;yes, another call
INVOKE RandLoop,-5,6 ;and this one last. No more INVOKEs so the loop terminates?
;no, there is no loop here, below have a loop
mov ecx,10 ;we will count it 10 times
again: ;again is a label to a loop, see below to understand
push ecx ;here, we save the ecx register, because I don't know if RandLoop2 modify this register, and yes, RandLoop2 modify that register
;so if in ecx we have 10, and do a call to RandLoop2, we don't know what have in ecx after that call.
INVOKE RandLoop2,1,6,0
pop ecx ;now, we get back that saved ecx register
dec ecx ; we subtract 1 from ecx, you can use "sub ecx,1"
cmp ecx,0 ;ecx is 0? if yes, so we have done it, if no, so do it again
jz done
jmp again
done: ;done is a label to get out of loop
call Crlf
exit
main ENDP
"call" is not equal of loop. Call is a jmp to another portion of your code, but after that code is done, so it "ret" to your code again.
"loop" is a jmp too, but it decrements the ecx register.
"call" do like a: "save(push) the address of where to return(the nex code after call), and after jmp to that procedure"
"ret" do like a: "restore(pop) the address saved, and after jmp to that address"
"loop" do like a: "jmp to some address and decrement ecx".
"invoke" is a bit more complex, but in essence is a "call".
You can use only "invoke" if you like, but to processor, invoke does not exist, only "call".Invoke is to make call more easy,
The same code as above, but here using loop.
main PROC
call Clrscr
call Randomize ;initialize random generator
INVOKE RandLoop,0,8 ;The use of INVOKE here is incremental from RandLoop? Grabs this one first,
INVOKE RandLoop,25,92 ;Then this one second
INVOKE RandLoop,-5,6 ;and this one last. No more INVOKEs so the loop terminates?
mov ecx,10 ;we will count it 10 times
again: ;again is a label to a loop, see below to understand
push ecx ;here, we save the ecx register, because I don't know if RandLoop2 modify this register
INVOKE RandLoop2,1,6,0
pop ecx ;now, we get back that saved ecx register
loop again ;the loop decrement ecx, after, compare it to see if it is zero, if yes, have done, if no, jmp to again
call Crlf
exit
main ENDP
If you see the RandLoop , it has a constant, to say, COUNT = 10. And if you change the COUNT to 1, and in another portion of your code , to say, RandLoop2, make a loop to call it 10 times.
Something nagged at me so I went back and found my Kip library. RandomRange returns a random number between 0 and n-1, so you will never get the last value. You have to increase the n value by 1 just before you call RandomRange to get the full range of possibilities. Picky, Picky, Picky.
Dave.
oops !
Quote from: KeepingRealBusy on April 24, 2011, 10:55:11 PMRandomRange returns a random number between 0 and n-1, so you will never get the last value.
Which is standard practice for most languages I know, including MasmBasic (http://www.masm32.com/board/index.php?topic=12460.msg124900#msg124900) and GfaBasic.
yah - old basic was the same way
Quote from: jj2007 on April 25, 2011, 06:41:07 AM
Quote from: KeepingRealBusy on April 24, 2011, 10:55:11 PMRandomRange returns a random number between 0 and n-1, so you will never get the last value.
Which is standard practice for most languages I know, including MasmBasic (http://www.masm32.com/board/index.php?topic=12460.msg124900#msg124900) and GfaBasic.
My point exactly. If you want to get random digits between 0 and 9 you must call RandomRange with a value of 9+1 or you will never see a 9 digit.
?
I changed my invoke value from
INVOKE RandLoop2,1,6,0
to
INVOKE RandLoop2,1,10,0
and was about to pull up 9 a couple of times.
better to fix it here
that way, the INVOKES work as desired :U
mov eax,dwMaxVal
sub eax,dwMinVal
inc eax ;add this line
mov dwRange,eax
Your snail avatar sound be a rocket!
:)
nahhhh
they tell me how slow my code is everytime i make an attachment :lol