Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中使用x86风格的跳转表_C_Assembly_X86_Jump Table - Fatal编程技术网

在C中使用x86风格的跳转表

在C中使用x86风格的跳转表,c,assembly,x86,jump-table,C,Assembly,X86,Jump Table,我正试图在C中像这样做一个跳转表 cmp eax, dword 3 ;max number ja invalid ;default jmp [eax*4+jumptable] ;jump to handler invalid: retn jumptable: dd handle0, handle1, handle2, hand

我正试图在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

但是它工作不好。

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

void dohandler(int a, int b, void (*jumptable[4]) (int x))
    if (a >= 0 && a < 4)
        jumptable[a](b);
}
void-dohandler(inta、intb、void(*jumptable[4])(intx))
如果(a>=0&&a<4)
可跳表[a](b);
}

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

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);
}

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


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

switch语句对您做了什么?您应该决定是用C还是用ASM编程,然后这样做。switch。。没有我在这个项目上需要的那么灵活比如,300个case的switch语句并不理想。我会使用switch,但我有300多个case,它们的顺序从0到299。编译器是否无法为该switch生成一个跳转表?似乎大多数编译器在这个愿望上都有点古怪,有一个标志可以用来强制它并接受“结果”如果有的话,它试图避免。