flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
Mike Gonta 27 Dec 2011, 21:42
Here is a .switch macro that uses cmp/je instead of a jump table.
Each .case will jmp to .endswitch unless .continue is used. .default is optional. Code: use32 .switch [counter] .case 1 .case 2 mov eax, 2 .continue .case 5 mov eax, 3 .switch ebx .case 4 mov eax, 4 .case 5 mov eax, 5 .default nop .endswitch nop .default nop .endswitch Code: macro .switch variable { local continue, this, c_style, var local stat, default, exit local top, count, here, x, val, location local save_eax continue=0 this=0 c_style=0 save_eax=0 match =c x, variable \{ var equ x c_style=1 stat equ \} match =stat x, stat variable \{ var equ x \} restore stat if ~var eq eax save_eax=1 push eax if var in <al, ah, ax, bl, bh, bx, cl, ch, cx, dl, dh, dx, bp, di, si> movzx eax, var else match x y, var \{ movzx eax, var stat equ \} match =stat, stat \{ mov eax, var \} restore stat end if end if label top DWORD repeat count cmp eax, DWORD 0 je NEAR $ end repeat if defined default jmp default else if save_eax jmp exit-1 else jmp exit end if end if macro .case [value] \{ \common if this if c_style | continue continue=0 if save_eax jmp $+3 end if else jmp exit align 16 end if end if continue=0 virtual dd $ load here DWORD from $$ end virtual if save_eax pop eax end if \forward this=this+1 match =stat a-b, stat value \\{ x equ a val equ b stat equ \\} match =stat b, stat value \\{ x equ val equ b \\} restore stat location=top+(11*this) if ~x eq if x<>0 store DWORD x at location-10 ; cmp eax, DWORD x store DWORD 11 at location-4 store BYTE 82h at location-5 ; jb .1 this=this+1 location=location+size end if store DWORD val at location-10 ; cmp eax, DWORD val store DWORD here-location at location-4 store BYTE 86h at location-5 ; jbe here else ;.1: store DWORD val at location-10 ; cmp eax, DWORD val store DWORD here-location at location-4 ; je here end if \} macro .break arg \{ match =.if x, arg \\{ JCOND exit, x stat equ \\} match =stat, stat \\{ jmp exit \\} restore stat \} macro .continue \{ continue=1 \} macro .default \{ if c_style | continue continue=0 if save_eax jmp $+3 end if else jmp exit align 16 end if default: if save_eax pop eax end if \} macro finish@switch \{ count=this if save_eax jmp $+3 pop eax end if exit: \} macro .table \{ local cmin, cmax local min, max, switch_table local counter local start, next, tab tab=1 cmin=0FFFFFFFFh cmax=0 if this if c_style if save_eax jmp next+1 else jmp next end if else if continue continue=0 if save_eax jmp next+1 else jmp next end if else jmp exit end if end if else continue=0 end if this=this+1 location=top+(11*this) if min store DWORD min at location-10 ; cmp eax, DWORD min store DWORD 11 at location-4 store BYTE 82h at location-5 ; jb .1 this=this+1 location=location+11 end if store DWORD max at location-10 ; cmp eax, DWORD max store DWORD start-location at location-4 store BYTE 86h at location-5 ; jbe start start: ;.1: jmp [switch_table+(eax-min)*4] align 4 label switch_table DWORD times max+1-min dd exit next: macro .case [value] \\{ \\common if ~tab if c_style | continue continue=0 if save_eax jmp $+3 end if else jmp exit align 16 end if end if tab=0 continue=0 virtual dd $ load here DWORD from $$ end virtual if save_eax pop eax end if \\forward match =stat a-b, stat value \\\{ x equ a val equ b stat equ \\\} match =stat b, stat value \\\{ x equ val equ b \\\} restore stat if val>cmax cmax=val end if if ~x eq if x<cmin cmin=x end if if x<>0 counter=val-x+1 else counter=val+1 end if else if val<cmin cmin=val end if counter=1 end if location=switch_table+(val-min)*4 repeat counter store DWORD here at location location=location-4 end repeat \\} macro finish@table \\{ max=cmax min=cmin \\} \} } macro .endtable { finish@table purge .case, finish@table } macro .endswitch { finish@switch purge .case, .break, .continue, .default, finish@switch } Last edited by Mike Gonta on 14 Oct 2013, 09:27; edited 11 times in total |
|||
![]() |
|
typedef 27 Dec 2011, 22:10
isn't this enough though ?
Code: cmp [mem32], imm32 jne @F @@: cmp reg32, xxx jne @F @@: ... ![]() |
|||
![]() |
|
l_inc 02 Jan 2012, 23:01
Mike Gonta
Could you write a version, that optimally combines jump tables and comparisons? That was my intention for some time, just didn't get to it. |
|||
![]() |
|
Mike Gonta 03 Jan 2012, 00:51
l_inc wrote: Could you write a version, that optimally combines jump tables and comparisons? The total number of cases vs the total number of jump table slots. What would be the optimal criterion? For example: Code: if cases>3 & slots<(cases*2) jump_table else comparisons end if Code: .switch <variable> .case 1 .case 5 .table .case 10 .case 11 .case 12 .case 13 .endtable .case 20 .endswitch Last edited by Mike Gonta on 14 Oct 2013, 09:28; edited 2 times in total |
|||
![]() |
|
l_inc 03 Jan 2012, 11:48
Mike Gonta
Quote: Or how about mixing jump tables and comparisons in the same switch block? That's exactly what I meant: to build a binary decision tree, where the leafs are either the jump tables with continuous ranges, so that the highest inter-case difference is 2 (the condition "slots<(cases*2)" is then automatically satisfied), or single values. |
|||
![]() |
|
Mike Gonta 05 Jan 2012, 00:13
I've updated the .switch macro with .table / .endtable.
.case blocks within will use the jump table method. This allows the mixing of both methods in the same .switch block to provide a fully programmer controlled optimization. Code: use32 .switch .case 1 .case 2 .table .case 3 .case 4 .endtable .case 5 .default .endswitch Last edited by Mike Gonta on 14 Oct 2013, 09:28; edited 2 times in total |
|||
![]() |
|
l_inc 05 Jan 2012, 16:53
Mike Gonta
Thank you. The macro seems to be pretty complicated now. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2023, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.