The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: ic2 on March 06, 2008, 11:40:24 AM

Title: .REPEAT .BREAK .UNTIL
Post by: ic2 on March 06, 2008, 11:40:24 AM
I been trying hard for days.  I pick-up only a few new notes to get a idea of how to do it.  I been thru my old thread below a hundred times and I tried everything I could think of.  This is much difficult to understand than the WHILE & ENDWHILE with was tough also.  Theres nothing much on the web about it other than here.  That a long time searching.  Now I went back to school to study Programming for knowledge and Networking for a job and i'm crazy about it too.

Could someone give me a out-line of what this code is doing so I can translate it to raw assembler.

Also I commented out parts of this code in the file below and it still works...but  yOda coded it for a reason and  I need to know why instead of just using this short cut...  It still works but if it not needed I'll not use it.  I guest by now every one know this has been my favorite example since when.  What to do with this line is a trip:

UNTIL EAX == [edx+IMAGE_EXPORT_DIRECTORY.AddressOfNames] and the  .BREAK directive is the monkey in the middle throwing me out loop and I can't take it no more.


Thank in advance


;  repeatstart:
;  cmp eax,1
;  jne UNTIL_exitloop
;  code goes here
;  jmp repeatstart
;  UNTIL_exitloop:

.REPEAT

   MOV  EDI, [EBX]
   ADD   EDI, dwDllBase
   MOV  ESI, [szApi]         ;  szApi
   PUSH ECX                        ;  save the api string length
   REPZ CMPSB

   .IF ZERO?
      .BREAK
   .ENDIF

   POP  ECX
   ADD  EBX, 4
   INC  EAX
.UNTIL EAX == [edx+IMAGE_EXPORT_DIRECTORY.AddressOfNames]

;; .REPEAT
;; .BREAK
;; .UNTIL EAX == IMAGE_EXPORT_DIRECTORY.AddressOfNames[edx]



More about other parts of this Macro and Tranlation:

http://www.masm32.com/board/index.php?PHPSESSID=40c7f25605407fc8f0b01e3bb9942e5c&topic=5915.0

[attachment deleted by admin]
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Tedd on March 06, 2008, 01:55:13 PM
If you understand .while/.endw then .repeat/.until shouldn't cause you any trouble - the only real difference is that repeat checks the condition at the end of the loop, but while checks it at the start. The result being that while may never enter the loop, but repeat must go through it at least once.

mov ecx,10
.repeat
    dec ecx
.until ecx==0


As for .break -- in both .repeat and .while, it will jump out of the loop (from where execution will continue with the next instruction.)
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Jimg on March 06, 2008, 05:59:38 PM
You also need to move your pop up before the break, or you stack will not be correct.  e.g.
.REPEAT

   MOV  EDI, [EBX]
   ADD  EDI, dwDllBase
   MOV  ESI, [szApi]         ; szApi
   PUSH ECX                  ; number of characters to compare.  save the api string length for next time through loop
   REPZ CMPSB                ; look for difference between strings
   POP  ECX                  ; get back number of characters to check (and fix stack)
   .BREAK .IF ZERO?          ; quit if there was no difference
   ADD  EBX, 4
   INC  EAX       
   
.UNTIL EAX == [edx+IMAGE_EXPORT_DIRECTORY.AddressOfNames]

I would make a lot of other changes myself, but this should fix the obvious.
Title: Re: .REPEAT .BREAK .UNTIL
Post by: ic2 on March 06, 2008, 07:01:38 PM
Now I get it...  I tried everything but what mess me up is trying to fixing this

.UNTIL EAX == [edx+IMAGE_EXPORT_DIRECTORY.AddressOfNames]

to maybe this

cmp eax, edx
jne _BACK_TO_REPEAT

I don't know...
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Jimg on March 06, 2008, 07:16:41 PM
Again, without passing judgment on if the code works or not-

MyLoop:
   MOV  EDI, [EBX]
   ADD  EDI, dwDllBase
   MOV  ESI, [szApi]  ; szApi
   PUSH ECX           ; number of characters to compare.  save the api string length for next time through loop
   REPZ CMPSB         ; look for difference between strings
   POP  ECX           ; get back number of characters to check (and fix stack)
   jz DoneLoop
   ADD  EBX, 4
   INC  EAX       
   cmp eax,[edx+IMAGE_EXPORT_DIRECTORY.AddressOfNames]
   jne MyLoop
DoneLoop:

And if this still isn't what you are asking for, try again, I'll get it eventually.

Edit:  apparently you modified your previous post while I was entering the answer.  Still questions?
Title: Re: .REPEAT .BREAK .UNTIL
Post by: ic2 on March 06, 2008, 07:30:08 PM
Jimg, I think I did that a few times but it did not work, then I went wild with all kinds of other ways..  I could have did something backwards but can't wait to get how to see....  I think this would not assemble for me.  Should'n all the data be in EDX already.

cmp eax,[edx+IMAGE_EXPORT_DIRECTORY.AddressOfNames]

I can't wait to get home   Thanks Jimg
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Jimg on March 06, 2008, 07:34:16 PM
IMAGE_EXPORT_DIRECTORY.AddressOfNames is a constant equal to the number of bytes from the start of the structure to the element AddressOfNames.  Since edx doesn't change within the loop, it could be computed once before the start of the loop if that's what you want.
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Jimg on March 06, 2008, 07:49:11 PM
Deleted
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Jimg on March 06, 2008, 10:05:45 PM
You made somewhat a mess of the GetKernalBase routine also-  should be something like this-
GetKernelBase PROC USES EDI ESI, dwTopStack : DWORD

   MOV  EDI, dwTopStack        ; start the search
   AND  EDI, 0FFFF0000h        ; wipe the LOWORD !

GKLoop:
   .IF WORD PTR [EDI] == IMAGE_DOS_SIGNATURE
      MOV  ESI, EDI
      ADD  ESI, [ESI+03Ch]
      cmp dword ptr [esi],IMAGE_NT_SIGNATURE
      je DoneGK
   .ENDIF
   SUB EDI, 010000h
   .IF EDI < MIN_KERNEL_SEARCH_BASE
      MOV  EDI, 0BFF70000h
   .ENDIF
   jmp GKLoop

DoneGK:
   XCHG eax, EDI
   RET
GetKernelBase ENDP


And I think there is a serious error in the way it is called.  Nothing is pushed on the stack for the routine to use so it will pop one value off the stack before returning, which should seriously mess you up.
Title: Re: .REPEAT .BREAK .UNTIL
Post by: ic2 on March 07, 2008, 05:05:48 AM
I see, you change (POP ecx) position by placing the BREAK equivalent code (jz DoneLoop) under it to get back number of characters to check (and fix stack).  It worksing... I would have never thought to do that.  I work in the order that an working example is presented. I posted yOda original code for others.  I just spend my spare time every since trying to break it down to work for other assemblers such as POASM and FASM but lead to issues after issues to no-related issues. 

   POP  ECX
   jz DoneLoop
   ADD  EBX, 4
   INC  EAX       

Thank you

PS:

QuoteYou made somewhat a mess of the GetKernalBase routine also-  should be something like this-

Finally, so this is why my calls to the very first API under Visa overflows the buffer or something, and would never work.  No other OS other than Visa detected that and ran my complete mess with-out a flaw.  So it was'nt DEP fault in my case but it was my sloppy coding that caused errors. I used my version of yOda code in everything I done and none of them works under Visa.


QuoteAnd I think there is a serious error in the way it is called.  Nothing is pushed on the stack for the routine to use so it will pop one value off the stack before returning, which should seriously mess you up.

That's right, It displayed a empty MessageBox when I call GetKernelBase.  But when calling  GetProcAddr with it it magically it returned a API that I see in the return MessageBox and the programs would still work.  That always had me puzzled and keep me interested.  Finally, my three year mistery solved.  Who would ever guested other than a Pro.

QuoteNothing is pushed on the stack
I should go make an apology (somewhere) but I think I'll wait.
[/size]
Thanks again   

[attachment deleted by admin]
Title: Re: .REPEAT .BREAK .UNTIL
Post by: ic2 on March 07, 2008, 08:40:06 AM
QuoteAs for .break -- in both .repeat and .while, it will jump out of the loop (from where execution will continue with the next instruction.)

Ted I see what you mean...  Take a look at the original code and the changed version.  Note both  GetKernelBase which use (WHILE).

Under (mov EDI, 0BFF70000h) (BREAK) is going back into the loop.

Under GetProcAddr which use (REPEAT) (BREAK) is use to jump out of the loop.


:U :U :U  Now we ALL know for sure !!!

I based my (WHILE) on donkey suggestion, and used Shantanu Gadgil, Dizz and others logic and Jimg put the icing on the cake for (REPEAT) ... It can be quite confusing but if anyone review this example the confusion will cease.  Please check to make sure I label everything properly  based on these conclusions.  I think I got it right.

Bottom line (BREAK) can reverse depending.  I will be looking at UNTIL a little harder just in case...  and I like the Instruction...  jnb  _a_ENDWHILE  making the next jump really a (BREAK) Instruction.

works great for MASM and POASM

need minor adjustments to work for FASM
not this ... cmp  dword ptr [esi], 4550h
but this ... cmp  dword[esi], 4550h


Thank you again masm32 community


[attachment deleted by admin]
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Jimg on March 07, 2008, 04:16:56 PM
You're still not getting it.

Your code:
;---- GET ImageBase of kernel32.dll ----       

xor eax, eax
mov eax, esp ; PUSH dword ptr [ESP]

;PUSH [ESP]
CALL GetKernelBase

The "xor eax,eax" and "mov eax,esp" do absolutely nothing.
You commented out the push which put something on the stack for GetKernelBase to use so now the GetKernalBase proc will still screw up the stack when it closes out.

If you're not going to do the exception handler, you might as well remove any code having to do with SEH.

You've total removed this test:
   .IF WORD PTR [EDI] == IMAGE_DOS_SIGNATURE

assuming it will always be true, which probably isn't the case.

I don't know what your intent was, but you took some well written code and generally made a mess of it.  Now that you know more, start with the original and try again, you might learn something new.
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Rainstorm on March 07, 2008, 11:52:17 PM
ted wrote
QuoteAs for .break -- in both .repeat and .while, it will jump out of the loop (from where execution will continue with the next instruction.)
.break can be used only in .while & .repeat loops nowhere else, is that right ? & same for .continue  ?
Title: Re: .REPEAT .BREAK .UNTIL
Post by: ic2 on March 08, 2008, 11:21:27 AM
I want to take a crack at this question before I get confuse again.

Quote.As for .break -- in both .repeat and .while, it will jump out of the loop
This is what most were people was trying to tell me before at the other thread posted above and while googling... but I didn't get it.  It was said in many difference ways and backwards.

Quote(from where execution will continue with the next instruction.)
Then this statement made it all so clean and final ... After experence in breaking .WHILE down in yOda code this may have proven otherwise... I figure it depends on how you use it and with what jcc to make it repeat or exit ...

Quote.break can be used only in .while & .repeat loops nowhere else, is that right ?
WHILE / REPEAT is what .break was design for.   I bet .continue was a stand-along.  Doing my search for the past few weeks I can almost swear that I saw it in few places where .BREAK and .CONTINUE was used as STAND-ALONG code.  And if that was the case, it prove they can only be used to ( jump out of any loop design )... But when used with REPEAT or  WHILE it can do a lot more.  Unlike .CONTINUE  I think .BREAK has special design (maybe even un-documented) features to jump IN or OUT a loop.[/size]

I'm not really sure yet but i'm going to learn. These links may help.

.CONTINUE used a lot here with .WHILE
http://www.masm32.com/board/index.php?topic=8318.0

.CONTINUE used here with .REPEAT
http://www.masm32.com/board/index.php?topic=2942.0
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Tedd on March 08, 2008, 12:35:35 PM
.break will jump to the end of the loop (either .while or .repeat) it is inside.
.continue jumps to the start of its loop.

There could be the possibility to use it for other looping constructs, but as far a I know masm only support these two.
It doesn't make sense to use break/continue outside of a loop - where would they jump to? what is the start/end?
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Jimg on March 08, 2008, 03:12:48 PM
I really don't intend to muddy the waters here, but technically and semantically,

.break jumps out of the loop (either .while or .repeat) it is inside, just past the .until or .endw.
.continue jumps to the part of the loop where it checks for the terminating condition.
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Rainstorm on March 08, 2008, 06:16:06 PM
what is this code from the masm hlp doing exactly with .break .if   or should the .endw statement be right at the bottom
EXAMPLE
    mov eax, 100
    .while eax > 0
      sub eax, 1
    .endw

    msgloop:
      invoke GetMessage, ADDR msg,NULL,0,0
      .break .if eax == 0

      invoke TranslateMessage, ADDR msg
      invoke DispatchMessage,ADDR msg
    jmp msgloop
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Tedd on March 08, 2008, 07:32:23 PM
I don't know what that mess is ::)

The normal message loop would be:
    .WHILE TRUE
        invoke GetMessage, ADDR msg,NULL,0,0
        .BREAK .IF (eax == 0)
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
    .ENDW


Which translates to:
    @while:
        invoke GetMessage, ADDR msg,NULL,0,0
        test eax,eax
        jz @out
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
        jmp @while
    @out:
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Rainstorm on March 08, 2008, 08:41:30 PM
Tedd, thanks for clearing that & the code examples.

just one more question... : ) can the masm .break be used in an masm  switch block ?

in the win SDK there is this example
case WM_CONTEXTMENU:
    if (!OnContextMenu(hwnd, GET_X_LPARAM(lParam),
              GET_Y_LPARAM(lParam)))
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    break;


why is the break after the return there ? what sense does that make ?
Title: Re: .REPEAT .BREAK .UNTIL
Post by: jj2007 on March 08, 2008, 11:41:56 PM
Made a quick test with Olly:

nop
    .WHILE TRUE
        dec eax
        .BREAK .IF (eax == 0)
    .ENDW
nop
    .WHILE 1
        dec eax
        .BREAK .IF (eax == 0)
    .ENDW
nop
    .REPEAT
        dec eax
        .BREAK .IF (eax == 0)
    .UNTIL 0
nop
    .REPEAT
        dec eax
        .BREAK .IF (eax == 0)
    .UNTIL FALSE
nop

... translates to ...
00403FFE     90             NOP
00403FFF   > 48             DEC EAX
00404000   . 0BC0           OR EAX,EAX
00404002   . 74 02          JE SHORT ReTest.00404006
00404004   .^EB F9          JMP SHORT ReTest.00403FFF
00404006   > 90             NOP
00404007   > 48             DEC EAX
00404008   . 0BC0           OR EAX,EAX
0040400A   . 74 02          JE SHORT ReTest.0040400E
0040400C   .^EB F9          JMP SHORT ReTest.00404007
0040400E   > 90             NOP
0040400F   > 48             DEC EAX
00404010   . 0BC0           OR EAX,EAX
00404012   . 74 02          JE SHORT ReTest.00404016
00404014   .^EB F9          JMP SHORT ReTest.0040400F
00404016   > 90             NOP
00404017   > 48             DEC EAX
00404018   . 0BC0           OR EAX,EAX
0040401A   . 74 02          JE SHORT ReTest.0040401E
0040401C   .^EB F9          JMP SHORT ReTest.00404017
0040401E   > 90             NOP


Masm doesn't care whether you use .while TRUE or .while 1, and produces exactly the same code for the equivalent .rep until true... clever  :thumbu
Title: Re: .REPEAT .BREAK .UNTIL
Post by: jj2007 on March 08, 2008, 11:48:36 PM
Quote from: Rainstorm on March 08, 2008, 08:41:30 PM
just one more question... : ) can the masm .break be used in an masm  switch block ?
nope - Masm chokes
Quote
in the win SDK there is this example
case WM_CONTEXTMENU:
    if (!OnContextMenu(hwnd, GET_X_LPARAM(lParam),
              GET_Y_LPARAM(lParam)))
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    break;


why is the break after the return there ? what sense does that make ?

It doesn't make any sense, but certain C dialects allow "falling through". Shiver :tdown
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Rainstorm on March 09, 2008, 01:21:30 AM
QuoteIt doesn't make any sense, but certain C dialects allow "falling through". Shiver ThumbsDown
l o l ! at the *shiver*....masm is the only  language I've ever looked at & am trying to learn, so don't know anything about C

many thanks for clearing that up.


Title: Re: .REPEAT .BREAK .UNTIL
Post by: jj2007 on March 09, 2008, 09:37:51 AM
Apparently Java is also affected by that:

Common sense would indicate that after executing the instructions following a case statement, and having come across another case statement the compiler would then finish falling through the switch statement. However, for reasons best known to the designers of the language case statements only stop falling through when they come across a break statement.

http://www.jchq.net/tutorial/02_01Tut.htm

The designers of Java and C also had the bright idea that a ";" must tell their compilers that a linefeed will soon follow, and that flow control must be controlled by many many "{" and "}" characters. Try a Google search on "C programming" "repetitive stress injury"  :wink
Title: Re: .REPEAT .BREAK .UNTIL
Post by: BogdanOntanu on March 09, 2008, 12:13:28 PM
Quote from: jj2007 on March 09, 2008, 09:37:51 AM
Apparently Java is also affected by that:

Common sense would indicate that after executing the instructions following a case statement, and having come across another case statement the compiler would then finish falling through the switch statement. However, for reasons best known to the designers of the language case statements only stop falling through when they come across a break statement.

And I have seen many modern software that DOES use this feature (falling through the switch statement). For some desperate mental reason they do consider it "cool" and an acceptable programming practice. Also there are many programmers out there that consider that the more complicated and more special features of the compiler they use and the more obfuscated the code is ... the more intelligent they are.

It is also related to not loosing your job. If it take a long time for a new employee to understand your code (and the code is perfectly valid) they your job is "more safe".

Quote
The designers of Java and C also had the bright idea that a ";" must tell their compilers that a linefeed will soon follow, and that flow control must be controlled by many many "{" and "}" characters. Try a Google search on "C programming" "repetitive stress injury"  :wink

That way it is more easy for the parser ... :D

Rainstorm:
Maybe you should take a look at other programming languages also. Of course there is no thing like ASM but a good programmer should also know C and a few other programming languages. At least in order to be able to read code that demonstrates some algorithms.
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Tedd on March 09, 2008, 01:18:55 PM
Quote from: Rainstorm on March 08, 2008, 08:41:30 PM
just one more question... : ) can the masm .break be used in an masm  switch block ?

in the win SDK there is this example
case WM_CONTEXTMENU:
    if (!OnContextMenu(hwnd, GET_X_LPARAM(lParam),
              GET_Y_LPARAM(lParam)))
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    break;


why is the break after the return there ? what sense does that make ?

The masm 'switch' block is really just a macro that rewrites to an .if block; a compiled switch statement can be more complicated. Since there was no 'break' included with that macro set, it won't work (because it's really just inside an if, but then, it's not required either.)
The win sdk examples are mainly in C++, and standard C requires a break to end the current 'case' -- making it jump to the end of the switch statement (after all of the other 'cases.') C++ and Java copied the fall-through format mainly for compatibility (execution 'falls' into the next case's code unless there is a break to stop that.)
In that example, the break comes 'after' return because the return is actually inside the if (i.e. if true: return, else break.)
Title: Re: .REPEAT .BREAK .UNTIL
Post by: BogdanOntanu on March 09, 2008, 02:09:55 PM
Quote
In the win SDK there is this example
Code:
case WM_CONTEXTMENU:
    if ( !OnContextMenu(hwnd, GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)) )
    {
              return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    break;

why is the break after the return there ? what sense does that make ?

For C/C++ it makes perfect sense. That is because the return statement will be executed only if the if condition is true. Since there is no else statement then the code might still fall through on some situations. Hence the break statement is required unless the original programmer intended a fall through and in this case I do not think he did.
Title: Re: .REPEAT .BREAK .UNTIL
Post by: Rainstorm on March 10, 2008, 06:54:40 AM
ted, thx ..... that explaination was really helpfull.

bogdan, yes.. maybe i'll try a  high level language sometime. - at the moment am just trying to learn asm & in the process, reading & trying out stuff in the windows SDK that is quite vast & time consuming. - I've not so much as looked at any other language before starting out with asm- I usually kinda get the logic of the code examples in the sdk broadly speaking , ..in order to duplicate the functionality in asm,  but not everything as i don't know the syntax.

..appreciate the help all.

Rainstorm
-