1. Open fridge
2. Take out apple
3. Eat apple
4. Did I eat 10 apples yet?
4a. No, repeat 3
4b. Yes, close fridge and go relax now I am full.
3 - 4 would be a loop. How would we do that in Assembly? I will show you how using Assembly and using MASM "High Level" syntax
The CPU has an instruction for loops called loop, it has two requirement - a label to loop to and a counter, the ecx (Extended Count register) register is the counter for the loop instruction.
You would put the iteration count in ecx and loop will decrement ecx till it equals 0 then exit the loop.
Print* are debug macros included in the MASM32 package that will "print" to a debug window or the RadASM IDE output window.
This will print "Yummy Apple!" 10 times, exit the loop then print "I ate 10 apples, now I am full"
mov ecx, 10
EatRedApple:
PrintText "Yummy Apple!"
loop EatRedApple
PrintText "I ate 10 apples, I am full now"
Another way to do a loop is:
mov ecx, 10
EatBlueApple:
PrintText "A blue Apple?!?!"
dec ecx
test ecx, ecx
jnz EatBlueApple
PrintText "UGH, I ate 10 blue Apples YUCK"
What we are doing is
1. Setting our counter to 10
2. Doing something
3. Decreasing our counter - dec
4. Testing to see if the zero flag is set - test (test does a bit-wise logical AND on the source and destination WITHOUT
5. If zero flag is not set jump back to EatBlueApple - jnz = Jump if not zero
5a. If zero flag is set, then leave loop
Yet another loop:
mov ecx, 10
EatGreenApple:
PrintText "Green Apple, tart but yummy"
dec ecx
jnz EatGreenApple
PrintText "I ate 10 green apples, I have a tummy ache now"
This one is a little bit more optimized than the BlueApple loop, if we are decreasing our counter then when our counter is zero, the zero flag gets set so we don't have to compare/test for zero.
Incrementing counter loop:
xor ecx, ecx
RottenApple:
PrintText "Oh no, not rotten Apples!"
inc ecx
cmp ecx, 10
jne RottenApple
PrintText "Please no more rotten apples!"
We compare (cmp) our counter to 10 and if it is not 10 repeat RottenApple. jne = Jump if Not Equal. What cmp does in the CPU is subtract (SUB) the second operand from the first and sets ONLY the FLAGS registers.
Whereas the SUB instruction modifies the first operand.
So, this is what will happen:
Quote
dest > source then Carry Flag = 0 Zero Flag = 0
dest = source then Carry Flag = 0 Zero Flag = 1
dest < source then Carry Flag = 1 Zero Flag = 0
dest = source then Carry Flag = 0 Zero Flag = 1
dest < source then Carry Flag = 1 Zero Flag = 0
This is for unsigned numbers, signed numbers is a bit different.
Not to confuse you anymore than you are with Assembly, BUT... knowing what flags are set you can use different mnumonics with different encodings/sizes and for code readability.
So in the RottenApple, you could replace jne (Jump if Not Equal) with:
jnz (Jump if zero flag != 0) and have the same results.
So, what about using MASM and its High Level stuff? Ok, we will use 2 - a .while/.endw loop and a .repeat/.until loop. MASM has many HLL macros that make coding easier and cleaner looking, but I
wouldn't use them in speed critical loops, instead I would manually code a loop.
GreenApple loop with counter going 1 to 10
xor ecx, ecx
inc ecx
.while ecx <= 10
PrintText "Another apple"
inc ecx
.endw
We will start the counter @ 1. Sure we could
mov ecx, 1
but that is 5 bytes, while
xor ecx, ecx
inc ecx
is only 3 bytes
So, we first set our starting index, check to see if our counter is at its max (10), if not, do something (printtext), increase our counter then jump to the beginning.
Another way is to use a .repeat/.until going 0 to 10
xor ecx, ecx
.repeat
PrintText "Ah jeesh another apple?"
inc ecx
.until ecx == 10
A .while loop checks the condition at the beginning of the loop, while a .repeat/.until checks the condition at the end of the loop.
Can I "nest" loops? No, why would you want to do that? haha Of course you can!
xor ecx, ecx
.repeat
PrintText "Eating Apple"
.while dwGreenApple <= I_AM_FULL
.if dwGreenApple <=6
PrintText "Yum, green apple"
.else
PrintText "No more apples please"
.endif
inc dwGreenApple
.endw
inc ecx
.until ecx == I_AM_FULL
Those are all "simple" loops, they can get more complicated but using the HL syntax of MASM, it makes life easier.
Wait, wait... what is that .if/.else/.endif? Next tut folks, next tut :-)







MultiQuote


|