flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > switch-case with jump table |
Author |
|
Vasilev Vjacheslav 08 Jul 2005, 11:39
thanks, great macro
what about 'break' command? like in c/c++ switches somethins like this Code: switch [wmsg] case WM_CREATE ; ... break (jump to label1) case WM_DESTROY ; ... break (jump to label1) default ; ... endswitch label1: |
|||
08 Jul 2005, 11:39 |
|
Tomasz Grysztar 08 Jul 2005, 12:10
This macro work's rather like a Pascal switch, where each case after executing its code goes to the end of switch instead of continuing to the next case.
However it's easy to modify the above macro the the C-like version: Code: macro switch var { local table,min,max,def,done if ~ var eq eax mov eax,var end if if min sub eax,min jc def end if cmp eax,max-min ja def jmp [table+eax*4] table dd max+1-min dup def local cmin,cmax,flags flags = 0 macro case value \{ if flags and 1 = 0 cmin = value cmax = value flags = flags or 1 else if value < cmin cmin = value end if if value > cmax cmax = value end if end if virtual dd $ load dest@case dword from $-4 end virtual if value-min < max+1-min store dword dest@case at table+(value-min)*4 end if \} macro default \{ flags = flags or 4 def: \} macro break \{ jmp done \} macro finish@switch \{ if flags and 4 = 0 def: end if done: max = cmax min = cmin \} } macro endswitch { finish@switch purge case,default,break,finish@switch } used like: Code: switch [wmsg] case WM_CREATE ; ... break case WM_DESTROY ; ... break default ; ... endswitch |
|||
08 Jul 2005, 12:10 |
|
madmatt 09 Jul 2005, 05:25
How about a break command for the .while, .repeat, and .if macros too?
|
|||
09 Jul 2005, 05:25 |
|
mike.dld 09 Jul 2005, 06:06
'break' could be used not only at the end of case label, but also somewhere in the middle, allowing to jump to the next instruction after 'switch' (this is allowed in both C and Pascal). As an example, imagine a code like this:
Code: ... case 123: if (a > b) break; ... // execute if a <= b break; case ...: ... |
|||
09 Jul 2005, 06:06 |
|
Tomasz Grysztar 09 Jul 2005, 08:11
This is exactly how "break" works here, too.
|
|||
09 Jul 2005, 08:11 |
|
vid 10 Jul 2005, 18:34
"break" is just a jump somewhere - all code of .while, switch etc is just linear code without any modifications of stack so, you can "jump" out of it from any place to anywhere in code with regular lable and "jmp".
|
|||
10 Jul 2005, 18:34 |
|
IceStudent 21 Sep 2006, 10:06
Hi! I tried to use this macro, it very helpful.
But it needs in a some trick, because the local labels, defined after it, are lost his visibility: Code: switch [wmsg] case WM_CREATE ; ... case WM_DESTROY ; ... default jmp .ret endswitch ; ... .ret: ret You must replace local def, done variables to ..def, ..done with corresponding corrections in macro code. |
|||
21 Sep 2006, 10:06 |
|
Vasilev Vjacheslav 21 Sep 2006, 10:59
try to use 'jmp default.ret'
|
|||
21 Sep 2006, 10:59 |
|
IceStudent 21 Sep 2006, 13:55
Hm.. I tried it..
A switch table seems too big: Code: switch [uMsg] case WM_CLOSE mov eax,1 case WM_SHOWWINDOW mov eax,2 default xor eax,eax endswitch ...... MOV EAX,DWORD PTR SS:[EBP+C] SUB EAX,10 ; Switch (cases 10..18) JB SHORT ntlm_tes.00011109 CMP EAX,8 JA SHORT ntlm_tes.00011109 JMP DWORD PTR DS:[EAX*4+110D7] DD ntlm_tes.000110FB ; Switch table used at 000110D0 DD ntlm_tes.00011109 DD ntlm_tes.00011109 DD ntlm_tes.00011109 DD ntlm_tes.00011109 DD ntlm_tes.00011109 DD ntlm_tes.00011109 DD ntlm_tes.00011109 DD ntlm_tes.00011102 MOV EAX,1 ; Case 10 of switch 000110C6 JMP SHORT ntlm_tes.0001110B MOV EAX,2 ; Case 18 of switch 000110C6 JMP SHORT ntlm_tes.0001110B XOR EAX,EAX ; Default case of switch 000110C6 |
|||
21 Sep 2006, 13:55 |
|
ghfphx 11 Oct 2006, 17:52
Couldn't this also work for a switch case statement?
Code: macro switch var { local end, dest, def value@switch equ var dest@switch equ dest flag@switch = 1 end@switch equ end def@switch equ def jmp dest@switch } macro case value { if value = value@switch flag@switch = 0 dest@switch: end if } macro default { if flag@switch flag@switch = 2 def@switch: end if } macro break { jmp end@switch } macro endswitch { if flag@switch = 2 dest@switch: flag@switch = 0 jmp def@switch else if flag@switch = 1 dest@switch: end if end@switch: restore value@switch restore dest@switch ; restore flag@switch restore end@switch restore def@switch } The only thing is that for some reason, the default doesn't goes through a continuous loop unless you use a break statement. Also does anyone know how to restore constants to their old values? |
|||
11 Oct 2006, 17:52 |
|
vid 11 Oct 2006, 18:16
Quote: Also does anyone know how to restore constants to their old values? no direct way, as with equates. but you can store value in other constant |
|||
11 Oct 2006, 18:16 |
|
LocoDelAssembly 11 Oct 2006, 19:04
mmm, how about adding a feature like "constantVal push" and "constantVal pop"? fasm already get rid of such things at preprosessing time, is it very hard to implement for assembling time constants? The difference with preprocessing time is that "push" is implicit where in assembling time it would be explicit.
|
|||
11 Oct 2006, 19:04 |
|
Overflowz 09 Sep 2011, 02:11
can't it be done without destroying value ?
I mean, when I'm doing something like this, it destroys value. Code: mov eax,0 switch eax case 5 xor eax,eax break case 1 mov eax,5 break default mov ecx,-1 break endswitch nop after this, eax=-1(destroyed) and ecx=-1(default) Should I do this with pushes and pops ? or can someone add some functions to not destroy value ? Thanks. |
|||
09 Sep 2011, 02:11 |
|
typedef 09 Sep 2011, 03:10
I hope this will be in the next FASM update (if there's one at all)
|
|||
09 Sep 2011, 03:10 |
|
AsmGuru62 09 Sep 2011, 15:22
A simple CMP+JE/JNE is much more readable.
|
|||
09 Sep 2011, 15:22 |
|
LocoDelAssembly 09 Sep 2011, 17:40
AsmGuru62, Tomasz's macro assembles to something a little bit more complex than that (jump tables).
Overflowz, you'll need to test this, but I think that replacing: Code: if min sub eax,min jc def end if cmp eax,max-min ja def jmp [table+eax*4] With: Code: if min cmp eax,min jc def end if cmp eax,max ja def jmp [table+(eax-min)*4] |
|||
09 Sep 2011, 17:40 |
|
Overflowz 09 Sep 2011, 20:14
as I see, this will only work with EAX register (my guess, I'm newbie.) If this is what I say like that, could you just replace it to work with every regs, mem locations, etc.. ?
|
|||
09 Sep 2011, 20:14 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.