【问题标题】:Using x86 style jump table in C在 C 中使用 x86 样式的跳转表
【发布时间】:2011-06-25 08:42:09
【问题描述】:

我正在尝试像这样在 C 中做一个跳转表

    cmp     eax, dword 3                        ;max number
    ja      invalid                     ;default
    jmp     [eax*4+jumptable]           ;jump to handler
invalid:
    retn
jumptable:
    dd handle0, handle1, handle2, handle3
handle0:
    ....

等等

我从这个开始

void dohandler(int a, int b, void (*jumptable[4]) (int x))
    if (a > 3) return
    else jumptable[3 * 4](b);
}
int main() {
    void (*jumptable[4]) (int x);
    jumptable[0] = &handler1;
    ... etc

    dohandler(1,2,jumptable);
}
void handler1(int x) { ... }
.. etc

但效果不好..

【问题讨论】:

  • switch 声明对你做了什么?
  • 你应该决定是用C还是ASM编程,然后再做。
  • switch.. 不像我在这个项目中需要的那样灵活,例如,300 例的 switch 语句并不理想..

标签: c assembly x86 jump-table


【解决方案1】:

switch 将被编译为一个跳转表,就像你想要的那样,只要标签值不是太稀疏。为表达式使用小尺寸类型(如unsigned char)或屏蔽高位可能会有所帮助,因此编译器不会在跳转表跳转之前添加额外的“if-in-range”条件,但是这可能不是那么重要。

最重要的是,实验。使用gcc -S 检查程序集输出。

【讨论】:

  • 我会使用开关,但我有 300 多个案例,它们按从 0 到 299 的顺序排列
  • 编译器是否无法为开关生成跳转表?
  • 似乎大多数编译器在这个愿望上有点不稳定,希望有一个标志可以用来强制它并接受它试图避免的“后果”(如果有的话)。
【解决方案2】:

不确定,但我认为您有几个问题:

void dohandler(int a, int b, void (*jumptable[4]) (int x))
    if (a > 3) return
    else jumptable[3 * 4](b);
}

首先,您在引用跳转表时不使用a,我认为这对应于汇编版本中的eax 寄存器。其次,不要将它乘以 4。我认为这应该是指针的大小,而数组引用会为您做到这一点。所以你最终得到了这个:

void dohandler(int a, int b, void (*jumptable[4]) (int x))
    if (a > 3) return
    else jumptable[a](b);
}

【讨论】:

    【解决方案3】:

    jumptable 是一个指针数组。不要尝试缩放偏移量,只需索引您要引用的指针即可。

    void dohandler(int a, int b, void (*jumptable[4]) (int x))
        if (a >= 0 && a < 4)
            jumptable[a](b);
    }
    

    【讨论】:

      猜你喜欢
      • 2015-12-03
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 2012-04-13
      • 2019-05-02
      • 2017-03-29
      • 2014-08-04
      • 2010-10-20
      相关资源
      最近更新 更多