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)
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...
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
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
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 :(
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
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.
The version that Greg Falen designed years ago still works perfectly, the string version that Michael Webster did works just as well.
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:
>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.
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.
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.
>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
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
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
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
OK, jj2007, I will test it and report to you ;)
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
---------
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
jj2007 :t :eusa_clap:
It really works, I will test it more and come back to you :greenclp:
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?
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?
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
Just delete the "unsafe", and it will be safe (but 4 bytes longer) :P
m2m ecx, 18
Switch_ ecx
Thank you, jj2007 :t
Now, what about 64 bit? Are you CANDO CAN'TDO? ;)
Here it is - test yourself 8)
there is something wrong it throws this error:
1>simple.asm(251): error A2048: Operands must be the same size: 4 - 8
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]>)
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
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
jj2007, I am looking forward for a fixed version :biggrin:
Take your time :bgrin:
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 ;-)
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
Don't worry about comments, I've got it 8)
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
Thank you so much :t
That is a WOODOSWITCH macro :bgrin:
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