News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Nested loops in MASM32

Started by JRevor, March 12, 2010, 02:23:21 PM

Previous topic - Next topic

JRevor

Are the high-level loop macros .WHILE , .ENDW ... macros prepared to be used in nested loops? For instance

.WHILE something
   code
   .WHILE somethingelse
      code
   .ENDW
   code
.ENDW


I'm worried i might have problems with these, because i have a very complex algorithm to implement. Should i stick with labels ? or use loop macros?

Slugsnack

the macros can nest fine, yes.

JRevor

Thanks
EDIT : Any idea where i can have more information about how these macros are implemented?

jj2007

Quote from: JRevor on March 12, 2010, 02:33:46 PM
Thanks
EDIT : Any idea where i can have more information about how these macros are implemented?

By looking at them with OllyDbg. You will find out that the .Repeat loop is a tick more efficient than .While, and that .Break .if ... can be useful, too. Here is an example.

include \masm32\include\masm32rt.inc

.code
AppName db "Masm32:", 0

start:
mov ebx, 3
.Repeat
dec ebx
.Until Sign?

nop
mov ebx, 3
.Repeat
.Break .if sdword ptr ebx<=0
dec ebx
.Until 0

nop
mov ebx, 3
.While ebx>0
dec ebx
.Endw

nop
mov ebx, 3
.While 1
.Break .if sdword ptr ebx<=0
dec ebx
.Endw
inkey "OK"
exit
end start


<ModuleEntr>/$ BB 03000000        mov ebx, 3
0040100D    |> 4B                 /dec ebx
0040100E    |. 79 FD              \jns short 0040100D
00401010    |. 90                 nop
00401011    |. BB 03000000        mov ebx, 3
00401016    |> 83FB 00            /cmp ebx, 0
00401019    |. 7E 03              |jle short 0040101E
0040101B    |. 4B                 |dec ebx
0040101C    |. EB F8              \jmp short 00401016
0040101E    |> 90                 nop
0040101F    |. BB 03000000        mov ebx, 3
00401024    |. EB 01              jmp short 00401027
00401026    |> 4B                 /dec ebx
00401027    |> 83FB 00             cmp ebx, 0
0040102A    |. 77 FA              \ja short 00401026
0040102C    |. 90                 nop
0040102D    |. BB 03000000        mov ebx, 3
00401032    |> 83FB 00            /cmp ebx, 0
00401035    |. 7E 03              |jle short 0040103A
00401037    |. 4B                 |dec ebx
00401038    |. EB F8              \jmp short 00401032


donkey

There is a fundamental difference between the .repeat and .while macros, mainly at which point they test the condition and they are not generally interchangeable. If you're looking for speed you might be better off coding them manually as you can optimize the check for condition and jumps using test/or/and for condition checks and branch hints for the jumps, these will shave quite a bit of time off the loops. However if speed is not an issue, the standard loops either .repeat or .while depending on your requirements are fine, nest quite nicely and are fairly efficient as far as macros go.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Quote from: donkey on March 12, 2010, 05:50:27 PM
If you're looking for speed you might be better off coding them manually as you can optimize the check for condition and jumps using test/or/and for condition checks and branch hints for the jumps, these will shave quite a bit of time off the loops.

We should test it! How could we optimise the loop so that it runs faster?

include \masm32\include\masm32rt.inc
.686
include \masm32\macros\timers.asm ; get them from http://www.masm32.com/board/index.php?topic=770.0
LOOP_COUNT = 100000

.code
start:
counter_begin LOOP_COUNT, HIGH_PRIORITY_CLASS
mov ebx, 1000
.Repeat
dec ebx
.Until Sign?
counter_end
print str$(eax), 9, "cycles for .Repeat ... .Until", 13, 10

counter_begin LOOP_COUNT, HIGH_PRIORITY_CLASS
mov ebx, 1000
@@:
dec ebx
jns @B
counter_end
print str$(eax), 9, "cycles for manual coding", 13, 10

inkey chr$(13, 10, "--- ok ---", 13)
exit
end start

donkey

Hi jj2007,

Useless test, you're testing a repeat loop, he was asking about while loops. Branch prediction would miss most of the time in a while loop (actually every time but one) however a repeat loop would be getting hits every time but one. To summarize, .WHILE type loops can benefit from branch hints but .REPEAT type loops generally don't. Also, there is no complex test for condition to improve upon in your test, try to check to see if ebx = 4 instead, I would guess that the macro would just CMP however coding it by hand I would tend to use AND or TEST. I would write the tests myself but optimization bores me.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

hutch--

If the logic of a .WHILE loop will do the job, I would code it that way and see how it works. As mentioned they nest with no problems but keep in mind that if its an intensive loop in pure mnemonic code you may be able to bypass some of its overhead by coding the loop design manually. If you are making external function calls or API calls use the .WHILE loop for clearer coding.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

Quote from: hutch-- on March 12, 2010, 08:40:14 PM
If the logic of a .WHILE loop will do the job, I would code it that way and see how it works. As mentioned they nest with no problems but keep in mind that if its an intensive loop in pure mnemonic code you may be able to bypass some of its overhead by coding the loop design manually. If you are making external function calls or API calls use the .WHILE loop for clearer coding.

I agree 100% with Hutch and said as much in my original post, hand code if you need speed otherwise .WHILE/.ENDW is just fine.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Quote from: donkey on March 12, 2010, 08:46:19 PM
hand code if you need speed

Please show us how to do it. Just the inner loop, only three lines that show that you can speed up a while loop...

include \masm32\include\masm32rt.inc
.686
include \masm32\macros\timers.asm  ; get them from http://www.masm32.com/board/index.php?topic=770.0
LOOP_COUNT = 1000000

.code
start:
counter_begin LOOP_COUNT, HIGH_PRIORITY_CLASS
mov ebx, 1000
test ebx, ebx
.While !Sign?
dec ebx
.Endw
counter_end
print str$(eax), 9, "cycles for .While ... .Endw", 13, 10

counter_begin LOOP_COUNT, HIGH_PRIORITY_CLASS
mov ebx, 1000
@@:
dec ebx ; **** insert optimised manual while loop here ****
jns @B
counter_end
print str$(eax), 9, "cycles for manual while ... coding", 13, 10

inkey chr$(13, 10, "--- ok ---", 13)
exit
end start

donkey

You should code something, perhaps a manually coded WHILE loop, which is not what you have manually coded in your example. There is not much opportunity for optimization in  a simple loop so I will not bother, optimized loops are for real applications, not imaginary situations that have been designed to not respond to optimization.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

sinsi


.text:00401060 BB E8 03 00 00                          mov     ebx, 3E8h
.text:00401065 85 DB                                   test    ebx, ebx
.text:00401067 EB 01                                   jmp     short loc_40106A
.text:00401069                         loc_401069:                             ; CODE XREF: .text:loc_40106Aj
.text:00401069 4B                                      dec     ebx
.text:0040106A
.text:0040106A                         loc_40106A:                             ; CODE XREF: .text:00401067j
.text:0040106A 79 FD                                   jns     short loc_401069

How inefficient.

.text:00401065 85 DB                                   test    ebx, ebx
.text:00401067 EB 01                                   jmp     short loc_40106A

should be

.text:00401065 85 DB                                   test    ebx, ebx
.text:00401067 7? ??                                   js     short loc_40106C


I thought a while loop tested before, so you test the initial value before any processing e.g.

mov ebx,whatever
@@:
test ebx,ebx
js @f
dec ebx
jmp @b
@@:
Light travels faster than sound, that's why some people seem bright until you hear them.

hutch--

#12
Guys,

Just for the people who use the Campus, can we keep discussion on details for the Workshop or similar as we don't want to baffle a learner with technology.

I spliot the rest of the conversation off to the Workshop so that new members don't get dazzled with all of the extra comments.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php