2

我正在尝试像这样在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

但它工作不顺利..

4

3 回答 3

4

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

void dohandler(int a, int b, void (*jumptable[4]) (int x))
    if (a >= 0 && a < 4)
        jumptable[a](b);
}
于 2011-02-11T06:13:13.210 回答
3

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

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);
}
于 2011-02-11T06:14:34.473 回答
3

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

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

于 2011-02-11T06:15:23.333 回答