News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Fun (and trouble) with loops

Started by RedSkeleton007, September 09, 2015, 11:23:20 AM

Previous topic - Next topic

RedSkeleton007

First, let me share a little syntax comparison I found interesting:

In C++ code:

int i = 0;
int number = 5;
while(i < 5){
i++;
}
cout << "We have looped " << i << " times." << endl;


In masm32 code:

        mov ax,0
mov ecx,5
L1:
inc ax
loop L1


In both languages, we've looped 5 times, and got there by keeping track of how many times we have looped. It's interesting, though, how in C++ the loop counter counts forward and compares, while in assembly the program counts backwards instead, while watching for when the ECX register decrements to zero.

However, those rules don't help me understand the example from the review questions in my book:

What will be the final value of EAX in the following code:

   mov eax,0
   mov ecx,10 ;outer loop counter
L1:
   mov eax,3
   mov ecx,5 ;inner loop counter
L2:
   add eax,5
   loop L2 ;repeat inner loop
   loop L1 ;repeat outer loop

The answer in the back of the book says:
"This is a trick! The program does not stop, because the first loop instruction decrements to zero, and the second loop instruction decrements ECX to FFFFFFFFh, causing the outer loop to repeat."

WTF?!  :icon_eek: I'm sorry, but none of that makes any sense to me. NONE of it. Any help?

dedndave

first, - there is an icon above the Reply window that looks like this: #
it adds "code" tags
so - write the code, select it (highlight) - then click the icon
it will look like this, keeping the columns lined up
    code
    morecode


next, i would say that's a terrible example to publish for someone learning assembler - lol
you wouldn't see it in any book i wrote or recommended
   mov eax,0
   mov ecx,10 ;outer loop counter
L1:
   mov eax,3
   mov ecx,5 ;inner loop counter
L2:
   add eax,5
   loop L2 ;repeat inner loop
   loop L1 ;repeat outer loop


but, if you really want to understand it, then just examine the inner loop, alone
   mov eax,3
   mov ecx,5 ;inner loop counter
L2:
   add eax,5
   loop L2 ;repeat inner loop


now it makes sense
if you want to add the outer loop, one way might be to add PUSH and POP
(i am guessing that's where the book is leading you to)
   mov eax,0
   mov ecx,10 ;outer loop counter
L1:
   push ecx
   mov eax,3
   mov ecx,5 ;inner loop counter
L2:
   add eax,5
   loop L2 ;repeat inner loop

   pop ecx
   loop L1 ;repeat outer loop


whether or not you push EAX will change the result
but, the loop will function either way

dedndave

i might add.....

one big advantage of assembler...
you can keep a handful of variables in register, resulting in faster code
with high-level languages, those variables are often kept in memory (on the stack, sometimes)

rrr314159

dedndave is of course right except for one thing: the book's example is not so bad, because it demonstrates a trap to watch out for.

Consider the inner loop:


L2:
mov ecx, 5
; do any loop processing here, as long as you don't change the value of ecx
loop L2
; here ecx will always be 0


- the "loop" instruction decrements ecx; it it's nonzero it branches back to L, if zero, it falls thru. Thus it will always be zero when you fall thru.

Now, put another loop around that one:


L1:
; doesn't matter what ecx is set to here since it will be changed to 5 below
L2:
mov ecx, 5
; do any loop processing here, without changing value of ecx
loop L2
; here ecx will always be 0
loop L1:


- When it hits "loop L1:", ecx will always be 0. So that instruction will first subtract 1, making ecx = -1; then compare it to zero. Of course, -1 (i.e., 0FFFFFFFFh) is NOT zero so it will always branch back to L1: an infinite loop. That's not what you wanted!

- The book is demonstrating this mistake, so you won't do it in your code
I am NaN ;)

RedSkeleton007

Quote from: dedndave on September 09, 2015, 12:25:41 PM
i might add.....

one big advantage of assembler...
you can keep a handful of variables in register, resulting in faster code
with high-level languages, those variables are often kept in memory (on the stack, sometimes)

Of course with C++, you're also given the option to declare variables on the heap, which is much faster than storing their values in conventional memory.

hutch--

 :biggrin:


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    mov ecx, 5      ; count required
    xor eax, eax    ; the value to increment

  lbl:
    add eax, 1      ; increment the value
    sub ecx, 1      ; decrement the loop counter
    jnz lbl         ; loop again if ECX != 0

    print str$(eax),13,10

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start

RedSkeleton007

Quote from: dedndave on September 09, 2015, 12:22:41 PM

but, if you really want to understand it, then just examine the inner loop, alone
   mov eax,3
   mov ecx,5 ;inner loop counter
L2:
   add eax,5
   loop L2 ;repeat inner loop


So first you initialize eax with 3 and then tell the ecx register you want the loop to iterate 5 times.

Next you add 5 to the eax register, which, on the first iteration, would make the new value in eax 8?

If I'm correct so far, in the end, the final value in eax would be 28.

Am I correct?

Quote from: dedndave on September 09, 2015, 12:22:41 PM
now it makes sense
if you want to add the outer loop, one way might be to add PUSH and POP
(i am guessing that's where the book is leading you to)
   mov eax,0
   mov ecx,10 ;outer loop counter
L1:
   push ecx
   mov eax,3
   mov ecx,5 ;inner loop counter
L2:
   add eax,5
   loop L2 ;repeat inner loop

   pop ecx
   loop L1 ;repeat outer loop

You're so accurate it's scary. Yep, that's the exact solution the book gives. :t

zedd151


Quote
You're so accurate it's scary. Yep, that's the exact solution the book gives. :t

He probably wrote the book. lol

K_F

Quote from: RedSkeleton007 on September 09, 2015, 01:30:58 PM
Of course with C++, you're also given the option to declare variables on the heap, which is much faster than storing their values in conventional memory.
Depends where the heap is... but it's not in the registers AFAIK... so we must be looking at memory, most likely the stack (which is a memory block)  ;)
I've never tried to control the cache levels.. not sure if you can control it, or control it predictably as the overhead might negate the advantage... maybe someone knows, or has tried this.
'Sire, Sire!... the peasants are Revolting !!!'
'Yes, they are.. aren't they....'

jj2007

Quote from: RedSkeleton007 on September 09, 2015, 01:30:58 PMdeclare variables on the heap, which is much faster than storing their values in conventional memory.

There are all the necessary tools in The Laboratory to support your (false) claim with evidence :P

hutch--

> declare variables on the heap, which is much faster than storing their values in conventional memory

This is claptrap, memory is memory is memory, data is either stored in memory or stored in a register, their ain't nothing else.

dedndave

i suspect accessing stack variables via [EBP+/-xx] is improved over some other methods (xx being signed byte)
but, depending on cache status, direct addressing is probably a little faster
although, it does produce larger code - in some cases, that may negate the advantage

generally speaking, values in register are going to be the fastest

it does bring to light a big difference of writing in assembler vs a high level compiler
that is - you control which variables are stored where
tedious perhaps, but can have advantages

RedSkeleton007


dedndave


hutch--

 :biggrin:

Dave,

I would like to see that formula bracketed as it is ambiguous as it is.

(3+5)*5 = 40
3+(5*5) = 28