Jumptable to labels

Just starting out? Need help? Post your questions and find answers here.
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Jumptable to labels

Post by Josh »

mk-soft wrote:Ok. Goto is a faster, but you need all labels too.
With VT can you defined the right functions.
I don't think there is a large difference:
- You jump in your example to Procedures, I jump in my example to Labels
- Where you have to write the Procedures, I have to write the Labels
- You call it in your example VTable, I call it in my case JumpTable, but it's the same

I suspect that the small time difference is caused by an overhead at the procedures. But forgot this times, try to do the same with an other system and you can go smoking during processor is calculating.

The large difference is the case of application. If I have more code for each jump I prefer Procedures but if I have only smallest snippest for each jump I prefer to do it with labels in one procedure.

P.S.:
@idle
Thanks for the hint with EnableASM/DisableASM. With this it is possible using an array, with !jmp... it isn't (at least I do not know how it could work)
sorry for my bad english
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: Jumptable to labels

Post by djes »

Remember the good ol'days. :P You can save some cycles with equal size subroutines (padded with null), and you don't have to create a jumptable. I'm not in front of a computer, but basically the principle is

Code: Select all

;Fast "select...case" example
;(c)djes 2017

;Beware, no checking !
Procedure FastSelect(n.i)
  *Subroutine = ?SUBROUTINES + n<<8 ;<<8 means "* 256" ; if your subroutines are bigger than 256 bytes, you should change it and all the following aligns
  EnableASM
  JMP *Subroutine
  !align 256
  DisableASM
  SUBROUTINES:
  ;first code
  PrintN("First subroutine executed")
  ProcedureReturn
  !align 256
  ;second code
  PrintN("Second subroutine executed")
  ProcedureReturn
  !align 256
  ;third code
  PrintN("Third subroutine executed")
  ProcedureReturn
  !align 256
EndProcedure

OpenConsole()
FastSelect(1)
FastSelect(0)
FastSelect(2)
Input()
End
Edit: using «align» fasm macro
Edit: removed local labels
Edit: functional code
Last edited by djes on Sun Mar 19, 2017 11:37 am, edited 2 times in total.
User avatar
idle
Always Here
Always Here
Posts: 5042
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Jumptable to labels

Post by idle »

nice and easy djes, but it wont work on osx with the fasm anonymous labels

josh yes you can use an array instead of a data section.

Code: Select all

Macro JumpTo(adr)
  *AdrLabel = adr
  EnableASM
  jmp *AdrLabel
  DisableASM
EndMacro   

Procedure Jump (x)
  Dim jt(5) 
  jt(0) =?Label_000
  jt(1)= ?Label_001
  jt(2)= ?Label_002
  jt(3)= ?Label_003
  jt(4)= ?Label_004
  jt(5)= ?Label_005
    
  JumpTo(jt(x))
    
  LabelBack:
  
  ;Some other code

  ProcedureReturn

  Label_000: : Debug "X = 000" : Goto LabelBack
  Label_001: : Debug "X = 001" : Goto LabelBack
  Label_002: : Debug "X = 002" : Goto LabelBack
  Label_003: : Debug "X = 003" : Goto LabelBack
  Label_004: : Debug "X = 004" : Goto LabelBack
  Label_005: : Debug "X = 005" : Goto LabelBack

EndProcedure
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Jumptable to labels

Post by Keya »

idle but with that array you then have extra code (filling the array with values) every time the Jump proc is called, which seems counter-intuitive in regards to using a jump table to save a few cycles? i just checked and even with Static it's still a lot of overhead by comparison:

Code: Select all

  !int3
  Dim jt(5)
  jt(0) =?Label_000
  jt(1)= ?Label_001
  jt(2)= ?Label_002
  jt(3)= ?Label_003
  jt(4)= ?Label_004
  jt(5)= ?Label_005
  !int3
  JumpTo(jt(x))
  !int3
Dim:

Code: Select all

00401070   .  CC                    int3
00401071   .  8D1424                lea edx, dword ptr [esp]
00401074   .  52                    push edx
00401075   .  68 00000000           push 0
0040107A   .  68 15000000           push 15
0040107F   .  68 06000000           push 6
00401084   .  68 04000000           push 4
00401089   .  E8 C50F0000           call PureBasi.00402053
0040108E   .  BD FA104000           mov ebp, PureBasi.004010FA
00401093   .  55                    push ebp
00401094   .  8B6C24 04             mov ebp, dword ptr [esp+4]
00401098   .  58                    pop eax
00401099   .  8945 00               mov dword ptr [ebp], eax
0040109C   .  BD FC104000           mov ebp, PureBasi.004010FC
004010A1   .  55                    push ebp
004010A2   .  8B6C24 04             mov ebp, dword ptr [esp+4]
004010A6   .  58                    pop eax
004010A7   .  8945 04               mov dword ptr [ebp+4], eax
004010AA   .  BD FE104000           mov ebp, PureBasi.004010FE
004010AF   .  55                    push ebp
004010B0   .  8B6C24 04             mov ebp, dword ptr [esp+4]
004010B4   .  58                    pop eax
004010B5   .  8945 08               mov dword ptr [ebp+8], eax
004010B8   .  BD 00114000           mov ebp, PureBasi.00401100
004010BD   .  55                    push ebp
004010BE   .  8B6C24 04             mov ebp, dword ptr [esp+4]
004010C2   .  58                    pop eax
004010C3   .  8945 0C               mov dword ptr [ebp+C], eax
004010C6   .  BD 02114000           mov ebp, PureBasi.00401102
004010CB   .  55                    push ebp
004010CC   .  8B6C24 04             mov ebp, dword ptr [esp+4]
004010D0   .  58                    pop eax
004010D1   .  8945 10               mov dword ptr [ebp+10], eax
004010D4   .  BD 04114000           mov ebp, PureBasi.00401104
004010D9   .  55                    push ebp
004010DA   .  8B6C24 04             mov ebp, dword ptr [esp+4]
004010DE   .  58                    pop eax
004010DF   .  8945 14               mov dword ptr [ebp+14], eax
004010E2   .  CC                    int3
Static Dim:

Code: Select all

0040108C   .  CC                 int3
0040108D   .  BD 03114000        mov ebp, PureBasi.00401103
00401092   .  55                 push ebp
00401093   .  8B2D 30314000      mov ebp, dword ptr [403130]
00401099   .  58                 pop eax
0040109A   .  8945 00            mov dword ptr [ebp], eax
0040109D   .  BD 05114000        mov ebp, PureBasi.00401105
004010A2   .  55                 push ebp
004010A3   .  8B2D 30314000      mov ebp, dword ptr [403130]
004010A9   .  58                 pop eax
004010AA   .  8945 04            mov dword ptr [ebp+4], eax
004010AD   .  BD 07114000        mov ebp, PureBasi.00401107
004010B2   .  55                 push ebp
004010B3   .  8B2D 30314000      mov ebp, dword ptr [403130]
004010B9   .  58                 pop eax
004010BA   .  8945 08            mov dword ptr [ebp+8], eax
004010BD   .  BD 09114000        mov ebp, PureBasi.00401109
004010C2   .  55                 push ebp
004010C3   .  8B2D 30314000      mov ebp, dword ptr [403130]
004010C9   .  58                 pop eax
004010CA   .  8945 0C            mov dword ptr [ebp+C], eax
004010CD   .  BD 0B114000        mov ebp, PureBasi.0040110B
004010D2   .  55                 push ebp
004010D3   .  8B2D 30314000      mov ebp, dword ptr [403130]
004010D9   .  58                 pop eax
004010DA   .  8945 10            mov dword ptr [ebp+10], eax
004010DD   .  BD 0D114000        mov ebp, PureBasi.0040110D
004010E2   .  55                 push ebp
004010E3   .  8B2D 30314000      mov ebp, dword ptr [403130]
004010E9   .  58                 pop eax
004010EA   .  8945 14            mov dword ptr [ebp+14], eax
004010ED   .  CC                 int3
my original example is simply:

Code: Select all

  OpFunc = PeekI(?PIXELOP_JMPTABLE + OpIndex)
  ! jmp [p.v_OpFunc]

=
00401045   .  BD 00304000        mov ebp, PureBasi.00403000   ;?PIXELOP_JMPTABLE
0040104A   .  89EB               mov ebx, ebp
0040104C   .  031D E8304000      add ebx, dword ptr [4030E8]  ;+ OpIndex
00401052   .  53                 push ebx
00401053   .  E8 F80F0000        call PureBasi.00402050       ;PeekI()
00402050        8B4424 04          mov eax, dword ptr [esp+4]
00402054        8B00               mov eax, dword ptr [eax]
00402056        C2 0400            retn 4
00401058   .  A3 E0304000        mov dword ptr [4030E0], eax
0040105D   .  FF25 E0304000      jmp dword ptr [4030E0]
User avatar
idle
Always Here
Always Here
Posts: 5042
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Jumptable to labels

Post by idle »

yes true keya, I was just addressing josh's question if it can be done with an array, don't expect it to be used like that
probably should have made it global or asked why josh wants a dynamic jump table.
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Jumptable to labels

Post by Josh »

idle wrote:yes true keya, I was just addressing josh's question if it can be done with an array
Hehe, you did a additional work. Thats my f.... english. Sorry :(
Josh wrote:Thanks for the hint with EnableASM/DisableASM. With this it is possible using an array, with !jmp... it isn't (at least I do not know how it could work)
This was meant:
1) With EnableASM/DisableASM it is possible using an array (i.e. jmp *Addresses\i[4] is possible)
2) With !jmp... it is not possible using an array. Maybe it is possible, but I don't know how (i.e. !jmp dword [p.p_AdrLabel[4]] or similar is not possible)


P.S.: I used it here (to find in code about 16 lines from bottom) and only with EnableASM/DisableASM it was a little bit faster than mk-soft's version.
sorry for my bad english
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: Jumptable to labels

Post by djes »

idle wrote:nice and easy djes, but it wont work on osx with the fasm anonymous labels
Oups, I forgot to remove them, they're no more useful with align.
I've posted a functional code there : http://www.purebasic.fr/english/viewtop ... 41#p504541
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Jumptable to labels

Post by Keya »

Josh wrote:2) With !jmp... it is not possible using an array. Maybe it is possible, but I don't know how (i.e. !jmp dword [p.p_AdrLabel[4]] or similar is not possible)
yes you can use "!jmp dword [p.p_AdrLabel+4]" for 2nd, +8 for 3rd etc (obviously use +8 instead of +4 on x64)
User avatar
idle
Always Here
Always Here
Posts: 5042
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Jumptable to labels

Post by idle »

yes you can do it by index

Code: Select all

Macro JumpTo(adr)
 EnableASM
  jmp adr
  DisableASM
EndMacro   

Structure jtf  
  jt.I[0]
EndStructure  

Procedure Jump (x)
  Static *jt.jtf 
  If Not *jt
    *jt = AllocateMemory(6*SizeOf(Integer)) 
    *jt\jt[0] = ?Label_000 
    *jt\jt[1] = ?Label_001 
    *jt\jt[2] = ?Label_002 
    *jt\jt[3] = ?Label_003 
    *jt\jt[4] = ?Label_004
    *jt\jt[5] = ?Label_005  
  EndIf   
    
  JumpTo(*jt\jt[x])
    
  LabelBack:
  
  ;Some other code

  ProcedureReturn

  Label_000: : Debug "X = 000" : Goto LabelBack
  Label_001: : Debug "X = 001" : Goto LabelBack
  Label_002: : Debug "X = 002" : Goto LabelBack
  Label_003: : Debug "X = 003" : Goto LabelBack
  Label_004: : Debug "X = 004" : Goto LabelBack
  Label_005: : Debug "X = 005" : Goto LabelBack

EndProcedure

jump(3)
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Demivec
Addict
Addict
Posts: 4086
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Jumptable to labels

Post by Demivec »

Here's another version of the jump table code:

Code: Select all

Procedure Jump (x)

  DataSection
    DataSta:
  
    Data.i ?Label_000
    Data.i ?Label_001
    Data.i ?Label_002
    Data.i ?Label_003
    Data.i ?Label_004
    Data.i ?Label_005

  EndDataSection

  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    mov eax, [p.v_x]
    jmp dword [eax*4 + ll_jump_datasta]
  CompilerElse
    mov rax, qword [p.v_x]
    lea rcx, [ll_jump_datasta]
    jmp qword [rax*8 + rcx]
  CompilerEndIf
  
  DisableASM
  LabelBack:

  ;Some other code

  ProcedureReturn

  Label_000: : Debug "X = 000" : Goto LabelBack
  Label_001: : Debug "X = 001" : Goto LabelBack
  Label_002: : Debug "X = 002" : Goto LabelBack
  Label_003: : Debug "X = 003" : Goto LabelBack
  Label_004: : Debug "X = 004" : Goto LabelBack
  Label_005: : Debug "X = 005" : Goto LabelBack

EndProcedure

For i = 0 To 5
  jump(i)
Next
It might be nice to add some range checking before the jump is made.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: Jumptable to labels

Post by djes »

Demivec wrote:Here's another version of the jump table code:

Code: Select all

Procedure Jump (x)

  DataSection
    DataSta:
  
    Data.i ?Label_000
    Data.i ?Label_001
    Data.i ?Label_002
    Data.i ?Label_003
    Data.i ?Label_004
    Data.i ?Label_005

  EndDataSection

  EnableASM
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    mov eax, [p.v_x]
    jmp dword [eax*4 + ll_jump_datasta]
  CompilerElse
    mov rax, qword [p.v_x]
    lea rcx, [ll_jump_datasta]
    jmp qword [rax*8 + rcx]
  CompilerEndIf
  
  DisableASM
  LabelBack:

  ;Some other code

  ProcedureReturn

  Label_000: : Debug "X = 000" : Goto LabelBack
  Label_001: : Debug "X = 001" : Goto LabelBack
  Label_002: : Debug "X = 002" : Goto LabelBack
  Label_003: : Debug "X = 003" : Goto LabelBack
  Label_004: : Debug "X = 004" : Goto LabelBack
  Label_005: : Debug "X = 005" : Goto LabelBack

EndProcedure

For i = 0 To 5
  jump(i)
Next
It might be nice to add some range checking before the jump is made.
Near perfect ! Make the jump based on x type, and you have sort of polymorphism in PB. :mrgreen:
Post Reply