跳转表是什么?

68

请问有人能够解释一下跳转表的原理以及为什么它在嵌入式系统中是必需的吗?

7个回答

65

跳转表可以是函数指针数组或者机器码跳转指令的数组。如果你有一个相对静态的函数集(例如系统调用或类的虚拟函数),那么可以创建一张这样的表,并使用简单的索引进入数组并调用函数。这意味着根据所使用的表的类型,需要检索指针并调用函数或跳转到机器代码。

在嵌入式编程中这样做的好处包括:

  1. 索引比机器码或指针更节省内存,因此在资源受限的环境中有潜在的内存节省可能性。
  2. 对于任何特定的函数,索引将保持稳定,只需交换函数指针即可更改函数。

访问表会略微降低性能,但这不比其他虚拟函数调用更糟。


27

跳转表(Jump table),也被称为分支表(Branch table),是一系列无条件跳转到代码中另一个位置的指令。

你可以将它们看作是 switch(或 select)语句,其中所有情况都已填充:

MyJump(int c)
{
   switch(state)
   {
      case 0:
         goto func0label;
      case 1:
         goto func1label;
      case 2:
         goto func2label;
   }
}
请注意,这里没有返回——跳转到的代码将执行返回语句,并跳回到调用myjump的地方。
这在状态机中非常有用,可以根据状态变量执行某些代码。虽然还有许多其他用途,但这是其中一个主要用途。
它通常用于不想浪费时间操纵堆栈并且想要节省代码空间的情况下。在中断处理程序中,速度极其重要,并且只有单个变量知道引起中断的外设时,这尤其有用。这类似于带有中断控制器的处理器中的向量表。
一个用途是利用一颗价值60美分的微控制器为视频应用程序生成复合(电视)信号。微控制器并不强大——实际上它仅能够足够快地编写每个扫描线。跳转表将用于绘制字符,因为从内存加载位图并使用for()循环推出位图会花费太长时间。相反,有一个单独的跳转到字母和扫描线,然后是8或更多指令,直接将数据写入端口。
-Adam

5
我理解switch-case语句实际上被编译成跳转表。这似乎是一个多余的解释(跳转表就像开关,而开关又像跳转表,再像开关...)。 - ArtOfWarfare

6
跳转表通常(但不是专属)用于有限状态机,以使其变为数据驱动。
与嵌套的switch/case语句不同,
  switch (state)
     case A:
       switch (event):
         case e1: ....
         case e2: ....
     case B:
       switch (event):
         case e3: ....
         case e1: ....

你可以创建一个二维数组或函数指针,并调用handleEvent[state][event]

2

来自维基百科:

在计算机编程中,分支表(有时也称跳转表)是一种有效的程序控制转移方法,可以使用一张包含分支指令的表格将程序控制转移到程序的另一部分(或可能已被动态加载的不同程序)。分支表构造通常用于汇编语言编程,但也可能由编译器生成。

分支表由一个串行列表组成,其中包含无条件分支指令。通过使用由顺序索引乘以指令长度(在内存中占用的每个分支指令的字节数)创建的偏移量进行分支。它利用了分支的机器码指令具有固定长度并且可以被大多数硬件极其高效地执行这一事实,并且在处理易于转换为顺序索引值的原始数据值时最有用。给定这样的数据,分支表可以极其高效;它通常由以下步骤组成:可选地验证输入数据以确保其可接受;将数据转换为分支表中的偏移量,这通常涉及将其乘以或移位以考虑指令长度;并分支到由表的基础和生成的偏移量组成的地址:这通常涉及将偏移量加到程序计数器寄存器上。


1
一个跳转表在这里被描述,简单来说,它是一个基于某些条件应该跳转到的地址数组。例如,C语言中的switch语句通常被实现为一个跳转表,其中每个跳转条目将转到特定的“case”标签。
在嵌入式系统中,由于内存使用量很大,许多结构最好使用跳转表而不是更耗费内存的方法(如大量的if-else-if)。

1

维基百科总结得相当好:

在计算机编程中,分支表(有时称为跳转表)是一种有效的方法,用于使用分支指令表将程序控制(分支)转移到程序的另一部分(或可能已经动态加载的不同程序)。分支表结构通常在汇编语言编程时使用,但也可以由编译器生成。

... 在计算机早期,内存昂贵,CPU较慢,紧凑数据表示和高效选择方案非常重要,因此分支表和其他原始数据编码的使用很常见。如今,它们通常用于嵌入式编程和操作系统开发。

换句话说,在您的系统极度受到内存和/或CPU限制时,这是一种有用的结构,尤其是在嵌入式平台上经常出现这种情况。


0

跳转表,通常称为分支表,通常只由机器使用。

编译器创建一个汇编程序中所有标签的列表,并将所有标签链接到内存位置。跳转表实际上是一个参考卡片,指向函数、变量或任何标签在内存中存储的位置。

因此,当函数执行完毕时,它会跳回到其先前的内存位置或跳转到下一个函数等。

如果你说的是我想的那个,你不仅需要它们在嵌入式系统中,而且在任何类型的编译/解释环境中都需要。

Brian Gianforcaro


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接