Branch table: Difference between revisions

Content deleted Content added
m Typical implementation: <source lang="c">
Naruyoko (talk | contribs)
Combine examples under a single section
 
(27 intermediate revisions by 20 users not shown)
Line 1:
{{short description|Method of transferring program control to another part of a program}}
In [[computer programming]], a '''branch table''' or '''jump table''' is a method of transferring program control ([[Branch (computer science)|branching]]) to another part of a program (or a different program that may have been dynamically loaded) using a table of branch or jump [[Instruction (computer science)|instruction]]s. It is a form of [[multiway branch]]. The branch table construction is commonly used when programming in [[assembly language]] but may also be generated by a [[compiler]], especially when implementing an optimized [[switch statement]] where known, small ranges are involved with few gaps.
{{original research|date=November 2016}}
In [[computer programming]], a '''branch table''' or '''jump table''' is a method of transferring program control ([[Branch (computer science)|branching]]) to another part of a program (or a different program that may have been dynamically loaded) using a table of branch or jump [[Instruction (computer science)|instruction]]s. It is a form of [[multiway branch]]. The branch table construction is commonly used when programming in [[assembly language]] but may also be generated by a [[compiler]]s, especially when implementing an optimized [[switch statement]]s wherewhose known,values smallare rangesdensely arepacked involvedtogether.<ref>{{cite withbook few|last1=Page gaps.|first1=Daniel |title=A Practical Introduction to Computer Architecture |date=2009 |publisher=Springer Science & Business Media |isbn=9781848822559 |page=479}}</ref>
 
==Typical implementation==
Line 7 ⟶ 9:
# branching to an address made up of the base address of the branch table plus the just generated offset. This sometimes involves an [[addition]] of the offset onto the [[program counter]] [[Processor register|register]] (unless, in some [[instruction set]]s, the branch instruction allows an extra index register). This final address usually points to one of a sequence of unconditional branch instructions, or the instruction immediately beyond them (saving one entry in the table).
The following pseudocode illustrates the concept
<sourcesyntaxhighlight lang="c">
... validate x /* transform x to 0 (invalid) or 1,2,3, according to value..) */
y = x * 4; /* multiply by branch instruction length (e.g. 4 ) */
goto next( + y); /* branch into 'table' of branch instructions */
/* start of branch table */
next: goto codebad; /* x= 0 (invalid) */
Line 17 ⟶ 19:
... rest of branch table
codebad: /* deal with invalid input */
</syntaxhighlight>
</source>
 
==Alternative implementation using addresses==
Another method of implementing a branch table is with an [[Array data structure|array]] of [[Pointer (computer programming)|pointers]] from which the required [[Function (computing)|function's]] address is retrieved. ThisOriginally known as '''transfer vector''', this method is also more recently known under such different names as "[[dispatch table]]" or "[[virtual method table]]" but essentially performing exactly the same purpose. This pointer function method can result in saving one machine instruction, and avoids the indirect jump (to one of the branch instructions).
 
The resulting list of pointers to functions is almost identical to direct [[threaded code]], and is conceptually similar to a [[control table]].
Line 47 ⟶ 49:
 
==Disadvantages==
* Extra level of [[indirection]], which incurs a usually small performance hit.
* Restrictions in some programming languages, (although there are usually alternative ways of implementing the basic concept of multiway branching).
 
==Example==
 
=== 8-bit Microchip PIC assembly language ===
A simple example of branch table use in the 8-bit [[PIC microcontroller|Microchip PIC]] assembly language is:
<sourcesyntaxhighlight lang="pic16nasm">
movf INDEX,W ; moveMove the index value into the W (working) register from memory
addwf PCL,F ; add it to the program counter. eachEach PIC instruction is one byte
; so there is no need to perform any multiplication.
; Most architectures will transform the index in some way before
; adding it to the program counter.
 
table ; theThe branch table begins here with this label
goto index_zero ; each of these goto instructions is an unconditional branch
goto index_one ; of code.
goto index_two
goto index_three
 
index_zero
; codeCode is added here to perform whatever action is required when INDEX = zero
return
 
index_one
...
</syntaxhighlight>
</source>
 
Note: this code will work only if PCL < (table + index_last). To ensure this condition we may use an "org" directive. And if GOTO (PIC18F for example) is 2 bytes, this limits the number of table entries to less than 128.
 
==Jump= tableC example in C===
Another simple example, this time demonstrating a jump table rather than a mere branch table. This allows program blocks outside of the currently active procedure/function to be called:
<sourcesyntaxhighlight lang="c">
#include <stdio.h>
#include <stdlib.h>
Line 95 ⟶ 99:
 
/* Convert first argument to 0-3 integer (modulus) */
value = ((atoi(argv[1]) % 4) + 4) % 4;
 
/* Call appropriate function (func0 thru func3) */
Line 102 ⟶ 106:
return 0;
}
</syntaxhighlight>
</source>
 
==Jump table example in= PL/I ===
[[PL/I]] implements a jump table as an ''array of label variables''. These may be initialized in an unusual way by using a subscripted statement label. PL/I label variables are not simply the address of the statement, but usually contain additional information on the state of the code block to which they belong. Without the unusual initialization, this could also be coded with calls and an array of entry variables.
<pre>
<source lang=PLI>
declare lab (10) label;
declare x fixed binary;
Line 114 ⟶ 118:
lab(2): /* code for choice 2 */ ;
...
</sourcepre>
 
==Compiler generated branch tables==
 
Programmers frequently leave the decision of whether or not to create a branch table to the compiler, believing that it is perfectly capable of making the correct choice from the known search keys. This may be true for optimizing compilers for relatively simple cases where the range of search keys is limited. However, compilers are not as intelligent as humans and cannot have a deep knowledge of 'context', believing that a range of possible search key integer values such as 1, 2, 4, 6, 7, 20, 23, 40, 42, 50 & 1000 would generate a branch table with an excessively large number of empty entries (900+) for very little advantage. (A good optimizing compiler may then presort the values and generate code for a [[binary chop]] search, as a 'second best' option.) In fact, the application may be highly "time critical" and [[Computer data storage|memory]] requirement may not really be an issue at all.<ref>[{{cite web|url=http://www.netrino.com/node/137]|title=How to Create Jump Tables via Function Pointer Arrays in C and C++|first=Nigel|last=Jones|date=1 May 1999|publisher=|access-date=12 July 2008|archive-url=https://web.archive.org/web/20120212110151/http://www.netrino.com/node/137|archive-date=12 February 2012|url-status=dead}}</ref>
 
However, a little 'common sense' can transform this particular case, and many other similar cases, to a simple two-step process with very large potential savings&nbsp;–, while still eventually leaving the ultimate choice to the compiler&nbsp;–, but 'assisting its decision' considerably:
 
* First, test for search key=1000 and perform appropriate branch.
Line 129 ⟶ 133:
===Computed GoTo===
 
While the technique is now known as 'branch tables', early compiler users called the implementation '[[Computed goto|computed GoTo]]', referring to the instruction found in the Fortran series of compilers.<ref name="GNU">{{cite web|url=httphttps://wwwgcc.chemiegnu.fuorg/onlinedocs/gcc-berlin2.de/chemnet/use/info/g7795.3/g77_14g77_18.html#SEC587|title=UsingAlternate andEntry PortingPoints GNU Fortran|last=Coon|first=Ty(ENTRY)|date=19912001-06-0207|work=ASSIGNUsing and GOTOPorting GNU Fortran|publisher=Free Software Foundation|accessdate=20092016-0411-1025}}</ref><ref name="RET">{{cite web|url=http://www.chilton-computing.org.uk/acd/literature/reports/p008.htm|title=FORTRAN Compilers and Loaders|last=Thomas|first=R.E.|date=1976-04-29|work=ACD: Engineering Paper No 42|publisher=ACD|accessdate=2009-04-10}}</ref> The instruction was eventually deprecated in Fortran 90 (in favour of SELECT & CASE statements at the source level).<ref name="F90">{{cite web|url=http://www.soton.ac.uk/~fortran/fortran90/course.html|title=A Brief Introduction to Fortran 90|work=Decremental/Deprecated/Redundant Features|accessdate=2009-04-10}}</ref>
 
==Creating the index for the branch table==
Line 135 ⟶ 139:
Where there is no obvious integer value available for a branch table it can nevertheless be created from a search key (or part of a search key) by some form of arithmetic transformation, or could simply be the row number of a database or the entry number in an array containing the search key found during earlier validation of the key.
 
A [[hash table]] may be required to form the index in some cases. However, for single byte input values such as A-Z (or the first byte of a longer key), the contents of the byte itself ([[raw data]]) can be used in a two-step, "[[trivial hash function",<ref>[[Hash_function#Trivial_hash_function]]</ref>", process to obtain a final index for a branch table with zero gaps.
# Convert the [[raw data]] character to its numeric equivalent (example [[ASCII]] 'A' ==> 65 decimal, 0x41 hexadecimal)
# Use the numeric integer value as the index into a 256 entry 2-byte array, to obtain a second index (invalid entries 0; representing gaps, otherwise 1, 2, 3 etc.)
The array would be no larger than (256 x× 2) bytes&nbsp;– to hold all possible 16-bit unsigned (short) integers. for all possible 8-bit bytes.
If no validation is required, and only upper case is used, the size of the array may be as small as (26 x× 2) = 52 bytes.
 
==Other uses of technique==
Although the technique of branching using a branch table is most frequently utilizedused solely for the purpose of altering program flow&nbsp;– to jump to a program label that is an unconditional branch&nbsp;– the same technique can be used for other purposes.
For example, it can be used to select a starting point in a sequence of repeated instructions where drop through is the norm and intentional. This can be used for example by [[optimizing compiler]]s or [[Just-in-time compilation|JIT]] compilers in [[loop unrolling]].
 
==See also==
Line 155 ⟶ 161:
 
==External links==
{{Commonscat}}
* [http://en.wikibooks.org/wiki/360_Assembly/Branch_Instructions] Example of branch table in [[Wikibooks]] for [[IBM S/360]]
* [https://web.archive.org/web/20120212110151/http://www.netrino.com/node/137] Examples of, and arguments for, Jump Tables via Function Pointer Arrays in [[C (programming language)|C]]/[[C++]]
* [http://www.eventhelix.com/realtimemantra/Basics/CToAssemblyTranslation3.htm] Example code generated by 'Switch/Case' branch table in C, versus IF/ELSE.
* [http://www.eventhelix.com/realtimemantra/Basics/CToAssemblyTranslation2CToAssemblyTranslation3.htm] Example code generated forby array'Switch/Case' indexingbranch iftable structurein sizeC, isversus divisible by powers of 2 or otherwiseIF/ELSE.
* [http://www.eventhelix.com/realtimemantra/Basics/CToAssemblyTranslation3CToAssemblyTranslation2.htm] Example code generated byfor 'Switch/Case'array branchindexing tableif instructure C,size versusis IF/ELSEdivisible by powers of 2 or otherwise.
* [http://www.rmbconsulting.us/Publications/PointerToFunction.pdf] "Arrays of Pointers to Functions" by Nigel Jones
 
{{DEFAULTSORT:Branch Table}}
Line 165 ⟶ 172:
[[Category:Conditional constructs]]
[[Category:Articles with example C code]]
[[Category:Control flow]]