Author | Message | Time |
---|---|---|
tA-Kane | If you've a set of mutually exclusive integer values which select what code to run, is it always better to use a jump table? If not, when would it be better not to? Also, I've not read anything about jump tables for PPC ASM... how do you create one on x86 (perhaps I can take that knowledge and experiment with PPC)? Or, is a jump table just (pseudocode) "if value=this then jump to here, if value = this2 then jump to here2, etc" ? | April 9, 2003, 10:46 AM |
Skywing | [quote author=tA-Kane link=board=7;threadid=996;start=0#msg7386 date=1049885203] If you've a set of mutually exclusive integer values which select what code to run, is it always better to use a jump table? If not, when would it be better not to? Also, I've not read anything about jump tables for PPC ASM... how do you create one on x86 (perhaps I can take that knowledge and experiment with PPC)? Or, is a jump table just (pseudocode) "if value=this then jump to here, if value = this2 then jump to here2, etc" ? [/quote]Jump tables are typically used when a large number of values are defined within a similar range. Usually, you have two tables - one mapping an input value to an index into the second table, which has the address of a handler routine. A simple x86 example, assuming the value to be tested is in eax and has already been range checked/adjusted: [code]movzx al, byte ptr [indextable+eax] jmp dword ptr [handlertable+eax*4][/code] | April 9, 2003, 12:32 PM |
tA-Kane | Thanks. So, this pseudocode would be a jump table? [code] jump to (beginning of table plus (value*4)) (beginning of table) jump to myhandler1 jump to myhandler2 jump to myhandler3 etc [/code] Also, I assume *4 would be *8 on a 64 bit processor? If that's a jump table, then wouldn't you need to verify that value isn't an invalid number (which would result in jumping to bad code)? If that's the case, then you'd need to check to verify it's a good value. If you do that, then why not jump after verifying instead of using a jump table? | April 9, 2003, 12:52 PM |
Yoni | [quote author=tA-Kane link=board=7;threadid=996;start=0#msg7395 date=1049892746]So, this pseudocode would be a jump table? [code] jump to (beginning of table plus (value*4)) (beginning of table) jump to myhandler1 jump to myhandler2 jump to myhandler3 etc [/code][/quote] No, it's more like this: [code] jump to *(beginning of table plus (value*4)) (beginning of table) myhandler1 myhandler2 myhandler3 etc [/code] i.e., the jump table contains addresses, not jump instructions. | April 9, 2003, 2:25 PM |
tA-Kane | Thanks, Skywing and Yoni, you've answered my basic question. But, now I have more... :P *4, that's assuming the machine uses 32 bit memory addressing and/or runs on a 32 bit processor? Wouldn't you need to verify that value isn't an invalid number (which would result in jumping to bad code)? If the value isn't a contiguous integer (eg, first value being 1 jumps to the first pointer, value 2 jumps to the second, but value 3 is not expected, though value 4 jumps to a third pointer, and etc similar), then would it be better to do a check and jump if the check is true, or better to use a jump table (with "padding addresses" pointing to a "bad_value_provided" function)? | April 9, 2003, 4:08 PM |
Yoni | [quote author=tA-Kane link=board=7;threadid=996;start=0#msg7405 date=1049904485] *4, that's assuming the machine uses 32 bit memory addressing and/or runs on a 32 bit processor?[/quote] Yes. For code compiled for a 64-bit processor, the formula will use 8 instead of 4. The general "formula" can be written as something like: jumptable + value * sizeof(void*) [quote author=tA-Kane link=board=7;threadid=996;start=0#msg7405 date=1049904485]Wouldn't you need to verify that value isn't an invalid number (which would result in jumping to bad code)?[/quote] Yes. Here's an example (this uses C/C++ code, which can cause a jump table to be generated by the compiler/optimizer): Code that looks like this: [code]switch(x) { case 1: stuff1; break; case 2: stuff2; break; case 3: stuff3; break; } stuff4;[/code] Might be translated to something like (pseudocode): [code]jumptable[3] = { &stuff1, &stuff2, &stuff3 } if(x >= 1 and x <= 3) goto jumptable[x-1] else goto &stuff4[/code] Note that if you use Visual C++ (6.0 and above), there is a Microsoft-specific extension you can use: __assume(0); which means "this code should never be reached, *pokes optimizer*". Then code that looks like this: [code]switch(x) { case 1: stuff1; break; case 2: stuff2; break; case 3: stuff3; break; default: __assume(0); } stuff4;[/code] Might be translated to: [code]jumptable[3] = { &stuff1, &stuff2, &stuff3 } goto jumptable[x-1][/code] (The optimizer assumes x will never be anything other than 1, 2, or 3, so it drops the checking.) [quote author=tA-Kane link=board=7;threadid=996;start=0#msg7405 date=1049904485]If the value isn't a contiguous integer (eg, first value being 1 jumps to the first pointer, value 2 jumps to the second, but value 3 is not expected, though value 4 jumps to a third pointer, and etc similar), then would it be better to do a check and jump if the check is true, or better to use a jump table (with "padding addresses" pointing to a "bad_value_provided" function)?[/quote]If there are big gaps between values, maybe a jump table is not such a good idea. Whether a jump table or a bunch of cmp and jz instructions (or their equivalent in your processor architecture) are used is up to you (read: up to the optimizer). | April 9, 2003, 7:47 PM |
iago | On our homework (in c++) we used switches instead of if's, and he called it inefficient. But a single compare/jump is much more efficient than many jumps, so obviously our marker knows nothing (duh) | April 9, 2003, 10:13 PM |
FreakingDude | I don't understand why you are multiplying it by 4? please explain why you would multiply it by 4 on 32 bit and 8 on 64 bit and what would you multiply it by on 16 bit??? please help ^^ | April 11, 2003, 8:35 PM |
Kp | [quote author=FreakingDude link=board=7;threadid=996;start=0#msg7587 date=1050093316] I don't understand why you are multiplying it by 4? please explain why you would multiply it by 4 on 32 bit and 8 on 64 bit and what would you multiply it by on 16 bit??? please help ^^ [/quote] It's multiplied by the number of bytes in a single address. For 32 bit mode, this is 32/8 = 4. For 64bit mode, 64/8 = 8. For 16bit mode, 16/8 = 2. | April 11, 2003, 8:56 PM |
FreakingDude | but why? I don't understnad why you need to multiply it by the number of bytes, why does the computer need you to multiply it by the number of bytes? why can't you just use the address thats there? | April 11, 2003, 9:05 PM |
Skywing | [quote author=FreakingDude link=board=7;threadid=996;start=0#msg7591 date=1050095105] but why? I don't understnad why you need to multiply it by the number of bytes, why does the computer need you to multiply it by the number of bytes? why can't you just use the address thats there? [/quote]Because the address size depends on what addressing mode you're using (surprise!), and thus you need to adjust the table lookups based on the size of a pointer. | April 11, 2003, 9:32 PM |
Adron | Note that you have to do this for any array indexing when you are programming in assembly language. If items in your array aren't in sequential addresses (i.e. mostly byte-size) then you need to multiply your index by the size of an item. A high-level programming language (like C, VB, whatever) takes care of the multiplication for you. Although in C you have to be aware of it sometimes. | April 14, 2003, 9:45 AM |