The MASM Forum

General => The Workshop => Topic started by: habran on February 22, 2016, 08:57:29 PM

Title: bitRAKE's SWITCH MACRO
Post by: habran on February 22, 2016, 08:57:29 PM
Hello everyone :biggrin:
Does anyone know how to use this macro :dazzled::


Title Switch / Case
Author bitRAKE
Submitted by: bitRAKE
Date added: 2002-02-17 21:02:01
Date modified: 2002-02-17 21:02:01
Comments
This offers an optimized branching method for a large set of unordered cases.

Snippet
;#############################################
; Optimized Switch/Case Macro
; by bitRAKE (aka Rickey Bowers Jr.)
;#############################################


SwitchThreshHold = 3 ;when is a bad idea to partition


.switch MACRO
  SwitchNodes = 0
  SwitchDefault TEXTEQU <>
  SwitchExit TEXTEQU <>
ENDM


.case MACRO xVal:REQ, xNode:REQ
  @CatStr(<SwitchValue>, %SwitchNodes) = &xVal
  @CatStr(<SwitchNode>, %SwitchNodes) TEXTEQU <&xNode>
  SwitchNodes = SwitchNodes + 1
ENDM


.default MACRO def:REQ
  SwitchDefault TEXTEQU <&def>
ENDM


.endswitch MACRO sexit
  LOCAL TheEnd, ww, oo, temp1, temp2, temp3, temp4

  SwitchExit TEXTEQU <&sexit>

;; This is a bubble sort on the values of the case statements
;; the labels follow their associated values.
  ww = SwitchNodes
  WHILE ww
    ww = ww - 1
    oo = ww
    WHILE oo
      oo = oo - 1
      temp1 = @CatStr(<SwitchValue>, %oo)
      temp2 = @CatStr(<SwitchValue>, %ww)
;; We need MASM to evaluate this at assemble-time
%     IF &temp1 GT &temp2
;; Numberic values can be swaped easily
        @CatStr(<SwitchValue>, %oo) = &temp2
        @CatStr(<SwitchValue>, %ww) = &temp1
;; Strings are a little harder...
;; Get the variable names
        temp3 TEXTEQU @CatStr(<SwitchNode>, %oo)
        temp4 TEXTEQU @CatStr(<SwitchNode>, %ww)
;; Get the value of those varibles
;; MASM doesn't allow &@CatStr(...)!
        temp3 TEXTEQU &temp3
        temp4 TEXTEQU &temp4
;; Swap them
        @CatStr(<SwitchNode>, %oo) TEXTEQU &temp4
        @CatStr(<SwitchNode>, %ww) TEXTEQU &temp3
      ENDIF
    ENDM
  ENDM


;; This starts the trasversal of the array as if it were a bbtree
  .SwitchPartition 0, SwitchNodes - 1


;; Output the code for the case nodes that haven't been done already
  ww = SwitchNodes
  WHILE ww
    ww = ww - 1
;; Previously output nodes are cleared in the transveral
%   IFNB <@CatStr(<SwitchNode>, %ww)>
      @CatStr(<SwitchLabel>, %ww, <:>)
%     @CatStr(<SwitchNode>, %ww)
      IFNB <&SwitchExit>
%       &SwitchExit
      ELSE
        jmp SwitchExitLabel
      ENDIF
    ENDIF
  ENDM


SwitchDefaultLabel:

  IFNB <&SwitchDefault>
%   &SwitchDefault

    IFNB <&SwitchExit>
%     &SwitchExit
    ENDIF
  ENDIF

SwitchExitLabel:

ENDM



;; Transverse the sorted array of variables that was created for each
;; case statement like a balanced binary tree...
.SwitchPartition MACRO _min:REQ, _max:REQ
  LOCAL delta, mmin, HighHalf

  delta = _max - _min
  mmin = _min

  IF delta LT SwitchThreshHold
;; Output a string of nodes comparisons and a node on the end
    WHILE delta GT 0
%     cmp eax, @CatStr(<SwitchValue>, %mmin)
      je @CatStr(<SwitchLabel>, %mmin)
      mmin = mmin + 1
      delta = delta - 1
    ENDM
%   cmp eax, @CatStr(<SwitchValue>, %mmin)
    jne SwitchDefaultLabel
%   @CatStr(<SwitchNode>, %mmin)
;; Clear this label variable so we don't output the code again
    @CatStr(<SwitchNode>, %mmin) TEXTEQU <>
    IFNB <&SwitchExit>
%     &SwitchExit
    ELSE
      jmp SwitchExitLabel
    ENDIF
  ELSE
;; Output a branch test
    delta = _min + (delta/2)
%   cmp eax, @CatStr(<SwitchValue>, %delta)
    jg HighHalf
    je @CatStr(<SwitchLabel>, %delta)

;; Re-Enter this macro until we've tested all the nodes
;; note that we skip the node we just tested for.
    .SwitchPartition _min, (delta-1) ;; Lower half of the range
HighHalf:
    .SwitchPartition (delta+1), _max ;; High half of the range
  ENDIF
ENDM


© 2016 by Thomas Bleeker (MadWizard)
Title: Re: bitRAKE's SWITCH MACRO
Post by: qWord on February 23, 2016, 01:58:51 AM
Seems there is an bug in it: there are two lines like this:
IFNB <&SwitchExit>
If adding the expansion operator to that lines
%   IFNB <&SwitchExit>
the macros could be used as (e.g.):
mov eax,7 ; value to switch in eax

.switch
.case 1, <invoke foo1>    ; angle brackets could be omitted in this example...
.case 2, <invoke foo2>
.case 3, <invoke foo3>
.case 4, <invoke foo4>
.case 5, <invoke foo5>
.case 6, <invoke foo6>
.case 7, <invoke foo7>
.default <invoke foo100>
.endswitch
Not sure if that is the intended usage...
Title: Re: bitRAKE's SWITCH MACRO
Post by: HSE on February 23, 2016, 02:38:10 AM
It's some kind of tree:



        SwitchValue equ ebx  ; I imagine (SwitchValue it's not defined in the macro)

.switch
.case <evaluation1>, 0 ; number it's branch rank (up or down?)
       .case <evaluation2>, 1
       .case <evaluation3>, 1
                          .case <evaluation4> , 2
.case <evaluation5>,  0
.case <evaluation6>, 0
.default <invoke foo100>
.endswitch
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 23, 2016, 06:25:28 AM
Thanks qWord, thanks HSE :t
I have fixed that what qWord sugested %   IFNB <&SwitchExit> in the first post and now it works fine 8)
here is example:

;eax is the test value
.switch
.case 1, jmp subproc1    ; angle brackets could be omitted in this example...
.case 2, jmp subproc2
.case 3, jmp subproc3
.case 4, jmp subproc4
.case 5, jmp subproc5
.case 6, jmp subproc6
.case 7, jmp subproc7
.default jmp subproc8
.endswitch

produce this:
00007FF70A5110BC 83 F8 04           cmp         eax,4 
00007FF70A5110BF 7F 15                jg          main+1Eh (07FF70A5110D6h) 
00007FF70A5110C1 74 2A                je          main+35h (07FF70A5110EDh) 
00007FF70A5110C3 83 F8 01           cmp         eax,1 
00007FF70A5110C6 74 29                je          main+39h (07FF70A5110F1h) 
00007FF70A5110C8 83 F8 02           cmp         eax,2 
00007FF70A5110CB 74 22                je          main+37h (07FF70A5110EFh) 
00007FF70A5110CD 83 F8 03           cmp         eax,3 
00007FF70A5110D0 75 24                jne         main+3Eh (07FF70A5110F6h) 
00007FF70A5110D2 EB AC                jmp         subproc3 (07FF70A511080h) 
00007FF70A5110D4 EB 22                jmp         main+40h (07FF70A5110F8h) 
00007FF70A5110D6 83 F8 05             cmp         eax,5 
00007FF70A5110D9 74 10                je          main+33h (07FF70A5110EBh) 
00007FF70A5110DB 83 F8 06             cmp         eax,6 
00007FF70A5110DE 74 09                je          main+31h (07FF70A5110E9h) 
00007FF70A5110E0 83 F8 07             cmp         eax,7 
00007FF70A5110E3 75 11                jne         main+3Eh (07FF70A5110F6h) 
00007FF70A5110E5 EB B9                jmp         subproc7 (07FF70A5110A0h) 
00007FF70A5110E7 EB 0F                jmp         main+40h (07FF70A5110F8h) 

   280: ;eax is the test value
   281:    .switch
   282:    .case 1, jmp subproc1    ; angle brackets could be omitted in this example...
   283:    .case 2, jmp subproc2
   284:    .case 3, jmp subproc3
   285:    .case 4, jmp subproc4
   286:    .case 5, jmp subproc5
   287:    .case 6, jmp subproc6
   288:    .case 7, jmp subproc7
   289:    .default jmp subproc8
   290:    .endswitch
00007FF70A5110E9 EB AD               jmp         subproc6 (07FF70A511098h) 
00007FF70A5110EB EB A3               jmp         subproc5 (07FF70A511090h) 
00007FF70A5110ED EB 99               jmp         subproc4 (07FF70A511088h) 
00007FF70A5110EF EB 87                jmp         subproc2 (07FF70A511078h) 
00007FF70A5110F1 E9 7A FF FF FF   jmp         subproc1 (07FF70A511070h) 
00007FF70A5110F6 EB B0                jmp         subproc8 (07FF70A5110A8h) 

00007FF70A5110F8 
Title: Re: bitRAKE's SWITCH MACRO
Post by: HSE on February 23, 2016, 08:46:13 AM
Very different to the tree I was thinking!

Some dicussion remains in http://www.asmcommunity.net/forums/topic/?id=179

Is an optimization for runtime, not for coding  :(
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 23, 2016, 09:38:11 AM
HSE, I saw that before :biggrin:
qWord, there was not error actually, it works fine without your suggestion, so I edited again the macro in my first post
It is very interesting macro, however it could be improved a lot.
For example in my example above there is no need for a binary tree, it should create a jump table and execute a jump
like:
jmp [@jumptable+rax*8]
or create a hash table if cases are scattered

Title: Re: bitRAKE's SWITCH MACRO
Post by: qWord on February 23, 2016, 11:22:10 AM
Quote from: habran on February 23, 2016, 09:38:11 AM
it works fine without your suggestion,
Yes, but only for your example. However, the macro code is definitively  wrong, because IFNB <&textMacroID> is always true and the specified else-clause will never be called. Actual there are 4 bugs of this form in that macros.
Title: Re: bitRAKE's SWITCH MACRO
Post by: hutch-- on February 23, 2016, 12:36:44 PM
The version that Greg Falen designed years ago still works perfectly, the string version that Michael Webster did works just as well.
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 23, 2016, 01:01:38 PM
Quote from: hutch-- on February 23, 2016, 12:36:44 PM
The version that Greg Falen designed years ago still works perfectly

And that's an understatement ;-)

Quote from: jj2007 on May 05, 2013, 08:58:54 AMWe have a Switch/Case macro, and it has a lot more power (http://masm32.com/board/index.php?topic=1185.0) than its C equivalent.

That was a nice thread btw :greensml:
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 23, 2016, 02:51:14 PM
>qWord, can you please fix it and post it again here.
If you have some spare time try to add a jump table feature.
>hutch--, there is nothing wrong with those macros as long as you have few cases, however, if you have plenty, they would not be efficient. This one is much faster and with  a bit of improvement it can be even better.

I am doing a research to design the SWITCH - CASE hll for HJWasm and I think to create first a good MACRO and test it before implementing it would be a good idea.

Title: Re: bitRAKE's SWITCH MACRO
Post by: hutch-- on February 23, 2016, 04:01:57 PM
Habran,

Long ago I did message processing in a WndProc() that used a table instead of a sequential set of comparisons and you could not see the difference. Be careful what you wish for, added complexity for no gain.
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 23, 2016, 06:29:31 PM
Quote from: habran on February 23, 2016, 02:51:14 PMIf you have some spare time try to add a jump table feature.

Switch_ (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1285):
Quoteunder the hood it creates a jump table that is for long lists of cases much faster than the Masm32 macro

The emphasis is on "long". As Hutch rightly noted, the difference is rarely relevant.
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 23, 2016, 07:52:48 PM
>hutch--, as jj2007 said, emphasis is on long lists of cases, and you probably already know my second name is CANDO,
however, you didn't know that my third and real name is actually SIMPLIFIER :biggrin:
I am not gonna decrease quality of HJWasm, but enhance it, I will implement it only if we in this forum conclude that it will be nice new feature 8)
>jj2007, can you show me source and disassembly of some example with your Switch_, please
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 23, 2016, 08:11:30 PM
Quote from: habran on February 23, 2016, 07:52:48 PM>jj2007, can you show me source and disassembly of some example with your Switch_, please

See below (the macro itself is lines 524...618 of \Masm32\MasmBasic\MasmBasic.inc). I only added the PrintLine "end of loop" to the sample code (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1285). Disassembly covers the loop only; see in particular the long list of dd MbSw1D - one reason why it can be inefficient. And guess what happens if you add a Case_ 12345 ::)

            include \masm32\MasmBasic\MasmBasic.inc
            Init                                    ; ## Switch with jump table ##
            m2m ecx, -5
            PrintLine "----------------------------- testing the new MasmBasic Switch_ macro -----------------------------"
            .Repeat
                        Print Str$(ecx), Tb$
                        Switch_ ecx
                        Case_ -2
                                    PrintLine "Case -2"
                        Case_ 0
                                    PrintLine "Case NULL"
                        Case_ 10
                                    PrintLine "Case 10"
                        Case_ 18
                                    PrintLine "Case 18"
                        Case_ 14 .. 16
                                    PrintLine "Case 14 .. 16"
                        Default_
                                    PrintLine "---"
                        Endsw_
                        inc ecx
            .Until signed ecx>20
            PrintLine "----------------------------- end of loop -----------------------------"
            EndOfCode


Output:
----------------------------- testing the new MasmBasic Switch_ macro -
-5      ---
-4      ---
-3      ---
-2      Case -2
-1      ---
0       Case NULL
1       ---
2       ---
3       ---
4       ---
5       ---
6       ---
7       ---
8       ---
9       ---
10      Case 10
11      ---
12      ---
13      ---
14      Case 14 .. 16
15      Case 14 .. 16
16      Case 14 .. 16
17      ---
18      Case 18
19      ---
20      ---
----------------------------- end of loop -----------------------------


Disassembly:
0121107F             ³.  68 50902101        push offset ra_lbl2        ; ASCII "----------------------------- testing the new MasmBasic Switch_ macro -----------------------------"
01211084             ³.  6A 01              push 1
01211086             ³.  6A 02              push 2
01211088             ³.  E8 B9140000        call MbPrint
C0004                ³>  51                 push ecx
0121108E             ³.  6A 05              push 5
01211090             ³.  6A 00              push 0
01211092             ³.  6A 01              push 1
01211094             ³.  E8 8D2D0000        call Float2Asc
01211099             ³.  6A 7F              push 7F
0121109B             ³.  6A 02              push 2
0121109D             ³.  6A 02              push 2
0121109F             ³.  E8 A2140000        call MbPrint
012110A4             ³.  3B0D 2C112101      cmp ecx, [121112C]
012110AA             ³.  8B15 28112101      mov edx, [MbSw1L]
012110B0             ³. 7F 64              jg short MbSw1D
012110B2             ³.  03D1               add edx, ecx
012110B4             ³. 7C 60              jl short MbSw1D
012110B6             ³.  FF2495 30112101    jmp near [edx*4+1211130]
MbSw10               ³>  68 B4902101        push offset ra_lbl3        ; ASCII "Case -2"
012110C2             ³.  6A 01              push 1
012110C4             ³.  6A 02              push 2
012110C6             ³.  E8 7B140000        call MbPrint
012110CB             À. E9 B4000000        jmp MbSw1
MbSw11               Ú>  68 BC902101        push offset ra_lbl4        ; ASCII "Case NULL"
012110D5             ³.  6A 01              push 1
012110D7             ³.  6A 02              push 2
012110D9             ³.  E8 68140000        call MbPrint
012110DE             À. E9 A1000000        jmp MbSw1
MbSw12               Ú>  68 C8902101        push offset ra_lbl5        ; ASCII "Case 10"
012110E8             ³.  6A 01              push 1
012110EA             ³.  6A 02              push 2
012110EC             ³.  E8 55140000        call MbPrint
012110F1             À. E9 8E000000        jmp MbSw1
MbSw13               Ú>  68 D0902101        push offset ra_lbl6        ; ASCII "Case 18"
012110FB             ³.  6A 01              push 1
012110FD             ³.  6A 02              push 2
012110FF             ³.  E8 42140000        call MbPrint
01211104             À. EB 7E              jmp short MbSw1
MbSw14               Ú>  68 D8902101        push offset ra_lbl7        ; ASCII "Case 14 .. 16"
0121110B             ³.  6A 01              push 1
0121110D             ³.  6A 02              push 2
0121110F             ³.  E8 32140000        call MbPrint
01211114             ³. EB 6E              jmp short MbSw1
MbSw1D               ³>  68 E8902101        push offset ra_lbl8        ; ASCII "---"
0121111B             ³.  6A 01              push 1
0121111D             ³.  6A 02              push 2
0121111F             ³.  E8 22140000        call MbPrint
01211124             ³. EB 5E              jmp short MbSw1
01211126             ³   8BFF               mov edi, edi
MbSw1L               ³.  02000000           dd 00000002
0121112C             ³.  12000000           dd 00000012
01211130             ³.  BD102101           dd MbSw10
01211134             ³.  16112101           dd MbSw1D
01211138             ³.  D0102101           dd MbSw11
0121113C             ³.  16112101           dd MbSw1D
01211140             ³.  16112101           dd MbSw1D
01211144             ³.  16112101           dd MbSw1D
01211148             ³.  16112101           dd MbSw1D
0121114C             ³.  16112101           dd MbSw1D
01211150             ³.  16112101           dd MbSw1D
01211154             ³.  16112101           dd MbSw1D
01211158             ³.  16112101           dd MbSw1D
0121115C             ³.  16112101           dd MbSw1D
01211160             ³.  E3102101           dd MbSw12
01211164             ³.  16112101           dd MbSw1D
01211168             ³.  16112101           dd MbSw1D
0121116C             ³.  16112101           dd MbSw1D
01211170             ³.  06112101           dd MbSw14
01211174             ³.  06112101           dd MbSw14
01211178             ³.  06112101           dd MbSw14
0121117C             ³.  16112101           dd MbSw1D
01211180             ³.  F6102101           dd MbSw13
MbSw1                ³>  41                 inc ecx
01211185             ³.  83F9 14            cmp ecx, 14
01211188             ³. 0F8E FFFEFFFF      jle C0004
0121118E             ³.  68 EC902101        push offset ra_lbl9        ; ASCII "----------------------------- end of loop -----------------------------"
01211193             ³.  6A 01              push 1
01211195             ³.  6A 02              push 2
01211197             ³.  E8 AA130000        call MbPrint
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 23, 2016, 08:32:28 PM
It looks impressive :t
Can you run it without .repeat, with only one case, for example Case_ 18, and than send the disassembly and oututput
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 23, 2016, 10:00:02 PM
include \masm32\MasmBasic\MasmBasic.inc
  Init
  mov ecx, 3
  Switch_ ecx
  Case_ 0
PrintLine "0"
  Case_ 3
PrintLine "3"
  Default_
PrintLine "default"
  Endsw_
EndOfCode


0088107C             ³.  B9 03000000        mov ecx, 3
00881081             ³.  3B0D D0108800      cmp ecx, [8810D0]
00881087             ³.  8B15 CC108800      mov edx, [MbSw1L]
0088108D             ³. 7F 2B              jg short MbSw1D
0088108F             ³.  03D1               add edx, ecx
00881091             ³. 7C 27              jl short MbSw1D
00881093             À.  FF2495 D4108800    jmp near [edx*4+8810D4]
MbSw10               Ú>  68 50908800        push offset ra_lbl2
0088109F             ³.  6A 01              push 1
008810A1             ³.  6A 02              push 2
008810A3             ³.  E8 BE130000        call MbPrint
008810A8             À. EB 3A              jmp short MbSw1
MbSw11               Ú>  68 54908800        push offset ra_lbl3
008810AF             ³.  6A 01              push 1
008810B1             ³.  6A 02              push 2
008810B3             ³.  E8 AE130000        call MbPrint
008810B8             À. EB 2A              jmp short MbSw1
MbSw1D               Ú>  68 58908800        push offset ra_lbl4        ; ASCII "default"
008810BF             ³.  6A 01              push 1
008810C1             ³.  6A 02              push 2
008810C3             ³.  E8 9E130000        call MbPrint
008810C8             ³. EB 1A              jmp short MbSw1
008810CA             ³   8BFF               mov edi, edi
MbSw1L               ³.  00000000           dd 00000000
008810D0             ³.  03000000           dd 00000003
008810D4             ³.  9A108800           dd MbSw10
008810D8             ³.  BA108800           dd MbSw1D
008810DC             ³.  BA108800           dd MbSw1D
008810E0             ³.  AA108800           dd MbSw11
MbSw1                ³>  6A 00              push 0

Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 23, 2016, 10:26:28 PM
OK, jj2007, I will test it and report to you ;)
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 24, 2016, 12:01:52 AM
Are you kidding me :icon_eek:
What I was expecting is that you routine will not need to test for each occurrence and jump, but do something like this:
for 64 bit:
lea rax, @Jumptable
jmp [rax+rcx*8]

or for 32 bit:
jmp  @Jumptable[ecx*4]

not :
           cmp ecx,3
           jg @L1
           jmp  Case2
@L1:   cmp ecx,4
           jg @L2
           jmp  Case2
@L2:    cmp ecx,5
            jg @L3
           ---------
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 24, 2016, 12:17:05 AM
Quote from: habran on February 24, 2016, 12:01:52 AM
jmp  @Jumptable[ecx*4]

see disassembly:
jmp near [edx*4+8810D4]

P.S.: In case you meant the two jumps, attached a special high performance version for use with plain Masm32. It saves 4 bytes (i.e. the two jumps), and should be significantly faster, too. All you have to do is to specify "unsafe" as the second argument.

include \masm32\include\masm32rt.inc
include SwitchUnsafe.mac
.code
start:
  m2m ecx, 1
  Switch_ ecx, unsafe
  Case_ 0
print "0"
  Case_ 3
print "3"
  Default_
print "default"
  Endsw_
  inkey chr$(13, 10, "bye")
  exit
end start
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 24, 2016, 06:25:44 AM
jj2007 :t :eusa_clap:
It really works, I will test it more and come back to you :greenclp:
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 24, 2016, 08:36:35 AM
jj2007, this macro is a peace of art :dazzled:
There is only need to fix an overflow. If the number is greater than the greatest case than it jumps in a wilderness.
Can you make it to work in 64 bit?
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 24, 2016, 08:48:11 AM
Quote from: habran on February 24, 2016, 08:36:35 AMThere is only need to fix an overflow. If the number is greater than the greatest case than it jumps in a wilderness.

I don't understand. Can you post an example please?
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 24, 2016, 09:13:56 AM
include \masm32\include\masm32rt.inc
include SwitchUnsafe.mac
.code
start:
  mov ecx, 18                    ;this will produce that jump
  Switch_ ecx, unsafe
  Case_ 0
   print "0"
  Case_ 3
   print "3"
  Default_
   print "default"
  Endsw_
  inkey chr$(13, 10, "bye")
  exit
end start
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 24, 2016, 10:04:39 AM
Just delete the "unsafe", and it will be safe (but 4 bytes longer) :P

  m2m ecx, 18
  Switch_ ecx
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 24, 2016, 02:56:59 PM
Thank you, jj2007 :t
Now, what about 64 bit? Are you CANDO CAN'TDO? ;)
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 24, 2016, 06:11:22 PM
Here it is - test yourself 8)
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 24, 2016, 08:58:57 PM
there is something wrong it throws this error:
1>simple.asm(251): error A2048: Operands must be the same size: 4 - 8
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 24, 2016, 10:59:01 PM
mistake is somewhere here:
  @CatStr(<cmp >, tmp$, <, MbSw>, %MbSct, <L[4]>) ; max
  @CatStr(<mov rdx, MbSw>, %MbSct, <L>) ; min
  ifdifi <smode>, <unsafe>
@CatStr(<jg @MbSw>, %MbSct, <D>)
  endif
  @CatStr(<add rdx, >, tmp$)
  ifdifi <smode>, <unsafe>
@CatStr(<jl @MbSw>, %MbSct, <D>)
  endif
  @CatStr(<jmp MbSw>, %MbSct, <L[4*rdx+8]>)
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 25, 2016, 01:19:56 AM
Quote from: habran on February 24, 2016, 10:59:01 PM
mistake is somewhere here:
  @CatStr(<cmp >, tmp$, <, MbSw>, %MbSct, <L[4]>) ; max

Yes, it probably needs some adjustments, e.g. [8] instead of [4] etc
Title: Re: bitRAKE's SWITCH MACRO
Post by: TWell on February 25, 2016, 01:36:54 AM
include SwitchUnsafe64.mac
extern ExitProcess :proc

.data
s1 db "0",0
s3 db "3",0
sd db "default",0

.code
start:
  sub rsp, 40
  mov rcx, 18         ;this will produce that jump
  Switch_ ecx;, unsafe
  Case_ 0
   mov rcx, offset s1
  Case_ 3
   mov rcx, offset s3
  Default_
   mov rcx, offset sd
  Endsw_
  xor ecx, ecx
  call ExitProcess
end ;start
ml64 -c SwitchUnsafe64.asm
Microsoft (R) Macro Assembler (x64) Version 14.00.23506.0
Copyright (C) Microsoft Corporation.  All rights reserved.

Assembling: SwitchUnsafe64.asm
SwitchUnsafe64.asm(13) : error A2022:instruction operands must be the same size
Switch_(11): Macro Called From
  SwitchUnsafe64.asm(13): Main Line Code
SwitchUnsafe64.asm(13) : error A2022:instruction operands must be the same size
Switch_(15): Macro Called From
  SwitchUnsafe64.asm(13): Main Line Code
SwitchUnsafe64.asm(13) : error A2024:invalid operand size for instruction
Switch_(19): Macro Called From
  SwitchUnsafe64.asm(13): Main Line Code
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 25, 2016, 06:23:12 AM
jj2007, I am looking forward for a fixed version :biggrin:
  Take your time :bgrin:
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 25, 2016, 07:01:56 AM
Quote from: habran on February 25, 2016, 06:23:12 AM
jj2007, I am looking forward for a fixed version :biggrin:

No way, my friend :greensml:

I am forever stuck with 32-bit code. If you prefer 64 bits, fix it yourself - shouldn't be too difficult ;-)
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 25, 2016, 08:48:25 AM
In another words: "If you want a thing done well, do it yourself." - Napoleon Bonaparte :bgrin:
Can you, at least, put some comments to the 32 bit one, please ;)
I am impressed with your macro, and I think that this one is a pearl between pebbles :eusa_clap:
When I make it work in 64 bit, with your permission, I will implement it in HJWasm, and I will give you credits for it :t   
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 25, 2016, 10:47:29 AM
Don't worry about comments, I've got it 8)
Title: Re: bitRAKE's SWITCH MACRO
Post by: jj2007 on February 25, 2016, 12:37:30 PM
Quote from: habran on February 25, 2016, 10:47:29 AM
Don't worry about comments, I've got it 8)

Great! Here is Switch_ itself with comments, as it will appear in today's release of MasmBasic (http://masm32.com/board/index.php?topic=94.msg55559#msg55559). And of course, you have my permission ;-)

MbSct=0
Switch_ MACRO arg:REQ, smode
Local tmp$
  MbSct=MbSct+1
  MbC0=0 ; case 0 doesn't need first jmp, all other and endsw yes
  MbSwMax=0
  MbSwMin=07fffffffh
  MbSw$ equ <#>
  @MbSw CATSTR <@MbSw>, %MbSct
  if (opattr arg) eq atRegister
tmp$ equ <arg>
  else
mov eax, arg
tmp$ equ <eax>
  endif
  @CatStr(<cmp >, tmp$, <, MbSw>, %MbSct, <L[4]>) ; max: cmp arg, MbSw1L[4]
  @CatStr(<mov edx, MbSw>, %MbSct, <L>) ; min: mov edx, MbSw1L[0]
  ifdifi <smode>, <unsafe>
@CatStr(<jg @MbSw>, %MbSct, <D>) ; jg @MbSw1D ; default
  endif
  @CatStr(<add edx, >, tmp$) ; add edx, arg ; min+arg
  ifdifi <smode>, <unsafe>
@CatStr(<jl @MbSw>, %MbSct, <D>) ; jl @MbSw1D
  endif
  @CatStr(<jmp MbSw>, %MbSct, <L[4*edx+8]>)
ENDM

Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 25, 2016, 12:52:15 PM
Thank you so much :t
That is a WOODOSWITCH macro :bgrin:
Title: Re: bitRAKE's SWITCH MACRO
Post by: habran on February 25, 2016, 07:30:34 PM
After a little bit of testing I found out that this macro works fine as long as cases are close to each other,
however, if we have for example:
  .switch  somevar
  .case 3
    dosomething...
   .break
  .case 5
    dosomethingelse...
    .break
  .case 1000
     nowdodifferentthing...
  .default
    dousualthing...
  .endswitch
 
it will allocate 1000 * 4   bytes for 32 bit or 1000 * 8 bytes for 64 bit

So I will have to combine several algos for different types of cases

Anyway, this macro is amazing and I will take it as a base to develop the complex one.

bitRAKE's macro with a little bit of tweaking can be combined with jj's one for a binary tree