在C语言中,确保多段代码的汇编指令数是固定的

在C语言中,确保多段代码的汇编指令数是固定的,c,assembly,goto,dispatch,vm-implementation,C,Assembly,Goto,Dispatch,Vm Implementation,在我正在编写的虚拟机中,我希望能够以类似于以下伪代码的方式分派命令 add: reg[memory[pc+1]] = reg[memory[pc+1]] + reg[memory[pc+2]]; pc += 2; goto done; sub: reg[memory[pc+1]] = reg[memory[pc+1]] - reg[memory[pc+2]]; pc += 2; goto done; cmp: /* Would take more space than simply x =

在我正在编写的虚拟机中,我希望能够以类似于以下伪代码的方式分派命令

add: reg[memory[pc+1]] =  reg[memory[pc+1]] + reg[memory[pc+2]]; pc += 2; goto done;
sub: reg[memory[pc+1]] =  reg[memory[pc+1]] - reg[memory[pc+2]]; pc += 2; goto done;
cmp: /* Would take more space than simply x = x + y; */ goto done;

for(int pc = 0; memory[pc] != END; pc++) {
    goto currentPositionInMemorySomehow + (memory[pc] * lengthOfInstruction);
    done:
}

其中,内存是一个包含字节码的数组,pc是一个程序计数器。然而,要做到这一点,我们需要跳转到的每个位置在下一个块之前都有相同数量的指令。下拉到汇编不是一个选项,除非有一个极好的平台无关的汇编代码,它允许人们获取相同的代码并编译到Linux、Mac和Windows。不管处理器是什么,每个处理器都位于其顶部。非常感谢您提供的任何帮助。

您似乎想编写一些C代码,这些代码将编译成大小独立于目标平台的可执行代码。这完全是一个不切实际的目标。

虽然我不知道有什么方法可以完全实现您想要的(我所知道的唯一允许计算跳转的编译器是gcc),但我建议您只使用一个
开关
,最合适的优化编译器会将其转换为跳转表或计算跳转,以适合您的平台的方式正确处理指令对齐。

我假定第二条指令应称为
sub
,而不是
add
?FWIW,为什么每条指令的长度必须相同?C代码是内联的吗?为什么不使用跳转表呢?每次操作码+操作数的大小可以相同。即使操作码+操作数的大小不同,操作码的代码也可以移动指令指针(pc)。操作码知道其操作数的大小。-这就是我要做的。顺便说一句,C没有计算
goto
,如果它工作的话,它只是一个扩展。为什么不使用
开关
语句?编译器生成的跳转表(假设您得到的是跳转表)引入了一个额外的间接寻址,您需要乘法,但您确定这会花费您的成本吗?@SteveJessop:编译器在某些情况下甚至可能使用直接计算的跳转,因此可能没有任何额外的开销indirection@Hasturkun:没错,编译器可以通过插入NOP或其他方法来填充小的用例,从而使所有的用例大小相同。有编译器真的这么做吗?@Rudy我已经更新了这个问题,所以第二个add现在是sub。谢谢你的关注@我的印象是switch语句相当于if语句的压缩集。然而,我将不得不对此进行调查。我以前尝试过使用跳转表,但由于不希望我在数组中存储标签,我遇到了一大堆问题。我并不是说跨平台的可执行文件的大小必须是恒定的,而只是说跨平台的可执行文件的每个指令分支的大小必须是恒定的。然而,我不知道C编译器是否足够聪明来优化switch语句。所以我现在只使用其中的一个,然后添加一个JIT来弥补性能成本。