我正在创建一个虚拟处理器,是时候实现 mov 指令了
在真实的处理器中,mov 有许多变体,其中操作码本身指示要使用哪个寄存器
如果我没记错的话,结果是这样的:0xB8 - (mov eax, ...), 0xBB - (mov ebx,...)
因此,指令的长度为 5 个字节(32 位模式),其中 1 个字节是操作码,4 个字节是值
但我还想出了另一种办法,就是在操作码后面直接指明寄存器号,这样的话就会只有一条mov指令,长度为6个字节
嗯,这2种方法会对速度产生负面影响
1种方式,switch case链会更长(特别是如果mov在我的情况下有30个变化),这可能会影响所有指令的执行速度
在情况 2 中,mov 指令的执行速度会更慢,因为程序需要知道现在要使用哪个寄存器,这也会使指令的大小增加一个字节,相应地,可执行文件的大小也会增加
那么问题来了,哪种方法在速度上会更好,一条指令直接指示寄存器号,还是多条指令已经知道要做什么并且不需要计算任何东西
(我用C++编写处理器,必要时编译器是G++)
只要填充了所有或几乎所有可能的操作码值,switvh-case 链的长度并不重要。对于短链,编译器通常生成比较树,对于长链,编译器通常生成跳转表(示例)。
某些指令采用多个操作码是很正常的。或者一个操作码用于多个命令,考虑到对于某些命令而言并非所有可能的值都有意义。
例如:
从寄存器开始的 mov 指令和到寄存器中指定的地址的 mov 指令本质上是不同的操作,尽管它们具有相同的名称。给它们不同的操作码是有意义的。
固定值为0的异或指令是没有意义的。如果编译器需要,可以使用nop,并
xor AX, 0使用相应的代码进行任何其他操作(相同的ret或nop)...