Page 2 of 2
Re: Jumptable to labels
Posted: Sat Mar 18, 2017 4:00 pm
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)
Re: Jumptable to labels
Posted: Sat Mar 18, 2017 4:35 pm
by djes
Remember the good ol'days.

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
Re: Jumptable to labels
Posted: Sun Mar 19, 2017 1:58 am
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
Re: Jumptable to labels
Posted: Sun Mar 19, 2017 3:53 am
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]
Re: Jumptable to labels
Posted: Sun Mar 19, 2017 5:41 am
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.
Re: Jumptable to labels
Posted: Sun Mar 19, 2017 6:46 am
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.
Re: Jumptable to labels
Posted: Sun Mar 19, 2017 10:15 am
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
Re: Jumptable to labels
Posted: Sun Mar 19, 2017 8:45 pm
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)
Re: Jumptable to labels
Posted: Mon Mar 20, 2017 6:53 am
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)
Re: Jumptable to labels
Posted: Tue Mar 21, 2017 4:49 am
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.
Re: Jumptable to labels
Posted: Tue Mar 21, 2017 8:00 am
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.
