问题标签 [jump-table]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
739 浏览

c++ - 在 C/C++ 中避免重复和简单的 switch case?

我在互联网上找到了一段代码,它的目标非常简单,但它使用了一种丑陋的方法。假设,作者正在使用 switch case 来确定先前定义的 Enum 的一些(非连续)值是否属于它们的范围。如果是,则函数返回true,仅此而已。否则,它返回false.

它实际上看起来像这样:

由于编译器生成的跳转表,他们使用 switch case 是合理的(即使跳转表不一定意味着从我收集的内容中即时查找)。即便如此,这也会产生无数不必要的代码行。

我已经阅读了有关函数内联和使用函数指针数组的信息,但我不知道如何在这种特定情况下使用它。

我如何避免用这样一个简单的案例(没有双关语)写很多case X:

0 投票
1 回答
2181 浏览

c - 在 ARM 上的代码中切换 case 的跳转表位置

在 C/C++ 中,编译器可以将 switch 语句降低到跳转表。我注意到 ARM 和 x86 之间跳转表的位置不同。

x86

对于 x86(和 x86_64),跳转表通常放在函数之外(例如 .rodata)

手臂

对于 ARM,跳转表与函数代码交错。

上面的代码是用 生成的clang 3.5 -target arm-none-eabi -march=armv7,但类似的代码是用 生成的gcc

MIPS

为了完整起见,这里是 MIPS 上的 switch 语句的代码。跳转表放置在.rodata节中。

jumptable( 0x00401848) 的地址在.rodata.

上面的代码是用 clang 3.9 生成的。

问题

为什么在 ARM 架构上跳转表经常与函数代码交错,而在 x86 上却没有?

这个答案意味着缓存在 ARM 上的工作方式与它有关。还有其他原因吗?

0 投票
1 回答
1125 浏览

assembly - GAS x86:读取跳转表/解释 switch 语句

我正在尝试对一些装配进行逆向工程,我已经做到了这一点:

我可以看到我在这里看到的是一个 switch 语句,其中默认情况是 -0x4(%rbp) > 5,但我对一些指令感到困惑:

40074b 是否只是转到跳转表上的某个位置并将该指令推送到 rax 中,以便我们之后可以跳转到 switch case 中的正确位置(即第 400753 行)?

在这种情况下,我不知道如何解释我们的不同案例。如果我的理解是正确的,跳转表从地址 400928 开始,去那里我看到:

在这一点上,我几乎不知道我在看什么。大概使用第 400753 行,我们会跳转到该表中的某个位置,但是然后呢?还是我的理解完全错误?

0 投票
2 回答
2008 浏览

c - 在 C 中使用书面跳转表或 switch 语句是否更快?

所以,我想看看使用函数指针的跳转表与使用 switch 语句来执行许多这样的命令操作之间是否有任何区别。

这是我制作的组装链接的代码

这也是我的实际代码

我的问题是,根据该链接或代码中生成的程序集,在 switch 语句的情况下创建一堆小函数来完成操作,并创建一个指向这些函数的指针数组和用相同的枚举调用它们?

使用 gcc x86_64 7.1

汇编代码粘贴:

0 投票
3 回答
827 浏览

c++ - 跳转表/分支是否与取消引用函数指针相同?

我一直在尝试了解什么是跳转表,但我无法理解某些内容。从我看到的许多示例中,它们似乎几乎可以归结为这一点,或者至少这是它的一个版本:

这些似乎只是一个函数指针数组,由某个值/位置索引。那么跳转表是否只是索引函数指针数组?我对此非常好奇,因为我看到很多人说 switch 语句经常被编译到跳转表中作为性能指标。据我了解,通过以这种方式跳转到函数,它涉及指针取消引用和函数调用。我认为这两个对性能都不是很好。

该站点上的另一个答案说,通过这种方式“您正在添加一个 switch 语句不一定具有的函数调用开销。” 编译为跳转表的开关如何避免函数调用?

此外,这里有一个高度投票的答案说“跳转表可以是指向函数的指针数组或机器代码跳转指令数组。” 您将如何跳转到机器代码指令而不是取消引用指针?这更快吗?

两者之间的区别是在我上面的示例中,指针不必被取消引用,因为它可以被静态绑定?与在运行时传入随机数作为索引相反?

谢谢。

0 投票
2 回答
247 浏览

vba - 我可以在 VBA for Excel 中创建跳转表吗?

我编写了一个简单的翻译器/解析器来处理 EDI (830) 文档,使用多个Select Case语句来确定要执行的代码。我以二进制模式打开文件并将文档拆分为单独的行,然后将每一行拆分为各种元素,其中每行的第一个元素具有唯一的段标识符。

我的代码完全按照编写的方式工作。但是,Select Case需要检查每一个,Case直到找到匹配项或Case Else执行。我Case以这样一种方式对语句进行了排序,即最常出现的段(如循环的情况)被放置在最前面,以尽量减少实际执行代码之前的“检查次数”。

与其使用多个Select Cases,我更愿意为段标识符确定一个索引,并使用该索引简单地调用适当的例程。我在 C 和汇编程序中使用了跳转表,并且预计在 VBA 中可能会出现类似的功能。

0 投票
1 回答
62 浏览

c++ - 数组中的函数指针(nix c++)

尝试使用函数指针初始化数组时出现编译器错误。在不使用类的情况下,我可以很好地运行代码,但是当我将代码合并到一个类中时,我得到了错误。我想这更多的是我对类使用、范围解析运算符等的理解。任何帮助解决这个问题将不胜感激。

编译器吐出:

0 投票
2 回答
3959 浏览

binary - Binary Bomb Phase 3 - 对使用跳转表感到困惑

我正在尝试找出在二元炸弹实验室第 3 阶段拆除炸弹的正确输入。我发现输入必须是两个整数,并且第一个整数必须小于 7。我一直在使用任意第一个值 (1) 来尝试使用跳转表来计算第二个值,但我似乎无法得到答案。具体来说,我一直在这条线之后引爆炸弹0x0000000000400ffc <+165>: cmp 0x8(%rsp),%eax

任何帮助或指导将不胜感激。

函数phase_3的汇编代码转储:

0 投票
1 回答
81 浏览

pointers - high-speed case construct assembler + load DPTR fast - 8051

I'm currently implementing a serial routine for an 8051 IC (specifically AT89C4051) and I don't have much stack space or memory left, and in order for me to achieve a decent baud rate on the serial port (38K or better), I need to make a high speed case construct since in my serial port interrupt routine, I'm building a packet and checking it for validity.

Assume we are in the serial interrupt and R0 is the address to the memory space in which data is to be received. Let's assume start address is 40h

So here we go with a bunch of compares:

Branching via many compares

The above code might be practical at first but as the current byte in the packet to work on increases, the routine runs 2 clock cycles slower each time because of the extra "cjne" instruction processing. For example, if we are on the 7th byte, then "cjne" would happen many times because it has to scan through each case which adds slowness.

Branching via jump

Now I thought of using just a jump but I can't figure out how to load DPTR at high speed because the interrupt can get called even when some other process is using the value of DPTR.

I thought of this code:

In my code, R3 and R6 were free so I used them to store the old DPTR value but those mov instructions as well as loading the new DPTR value take 2 cycles each for 10 cycles total (including restoring old value).

Is there a faster way to process a case construct in 8051 assembly code so that my serial routine processes faster?

0 投票
0 回答
51 浏览

c - 使用函数指针时传递参数

我试图了解如何实现函数指针的二维表(以简化半复杂的 switch/case/if 构造)。

以下工作 - 经过一些争论 - 根据需要。

现在我想要的是将参数传递给函数 - 例如,更改void Phase(void)

void Phase(int mode) 并通过一些类似的构造调用它:

table[1][1](TRUE);

但我还没有弄清楚如何做到这一点。欢迎任何帮助。