我正在查看指令及其相应的操作码。“je”和“jz”等指令的操作码相同:
je,jz - 0x74 (8 bit)
je,jz - 0x0f84 (16/32 bit).
为什么我们有这样多余的指令?
是因为它使汇编编码更容易吗?也就是说,在某些情况下更容易理解“相等时跳转”,而在其他情况下更容易理解“在零上跳转”。但是这些天我们并没有真正在汇编中编码,所以它有帮助吗?
我们在学校读过的那本计算机体系结构书的老引语是什么?“x86 没有什么问题,只是其中很多没有意义。”
回答您的问题:可能是因为“跳转到零”和“如果相等则跳转”都是根据前一条指令的结果跳转到目标地址。也就是说,前一条指令的结果将零标志 (ZF) 设置为 1。JZ 可能用于“数学”,而 JE 可能用于“比较”。所以从程序员的角度来看,有两个助记符是有道理的。也许早期的汇编程序作者试图模仿另一种流行的汇编语言。
查看 Intel x86 的 Jcc 手册(一组条件跳转指令),我们可以看到 JZ 和 JE 本质上的意思是“如果相等(ZF=1)就跳转到附近”。然后文档实际上提到这对于某些跳转指令集很常见。
因为状态标志的特定状态有时可以用两种方式解释,所以为一些操作码定义了两个助记符。例如,JA(如果高于则跳转)指令和 JNBE(如果不低于或等于则跳转)指令是操作码 77H 的备用助记符。
它们只是同一指令的不同同义词。该指令只是基于 Z 标志进行分支。如果比较相等指令的结果为真,则设置 Z 标志。它也被设置它你测试一个恰好为零的值。
为什么有的说英语的人说卡车,有的说卡车?我们应该强迫每个人都遵守一个标准吗?所有的汉堡都应该是巨无霸……
首先,我们仍然在汇编中进行编程。足够多的人这样做,以至于其他人不必这样做。您的编译器严重依赖它。没有它,很难开发和调试编译器和处理器。如果没有编译器和处理器,我们会怎么做?
让汇编程序解析器在相等时接受跳转与在设置零位时跳转是微不足道的,它们是相同的功能,相同的指令。理解和使用标志的人(假设 z 标志很容易,但有符号和无符号进位并不容易)喜欢使用标志如果进位则跳转,如果为零则跳转等。根据这些特定数字的关系来思考的人对于该特定操作,希望看到如果相等则跳转,如果大于则跳转,如果小于等等。如果相等,我宁愿摆脱跳跃,如果小于则跳跃,等等,只有标志,如果 c 则跳跃,如果 c 清除则跳跃,如果 n==v 则跳跃,如果 n!=v 则跳跃,等等。
英特尔不是您会看到这一点的第一个或最后一个架构。我假设出于同样的原因,有些人认为状态寄存器中的位是打开还是关闭,而另一些人认为这比那个更大。从某种意义上说,只要处理器具有 z 标志,就知道 z 标志意味着相等,这是一个时代问题,但这与 x86 家族的时代及其愚蠢的指令集无关。以这种方式对开发人员友好会吸引开发人员使用您的处理器,在工具中实现它是微不足道的。
如果您真的想为此烦恼,为什么同一指令集有 intel 语法和 AT&T 语法?如果设置了零位指令,则如果相等(设置零位)与设置零位时的跳转,则这种精神错乱远远超出了跳转。
即使现在使用不多,英特尔汇编语言也很古老。请记住,最初的 8086 和 8088 处理器来自 1970 年代...
曾几何时,当我们还在为 IBM PC/XT 之类的东西编写汇编代码时,有几条指令很有意义,比如
CMP AX, BX
JE Somewhere
或者
AND AX, BX
JZ somewhere_else
他们碰巧映射到相同的硬件指令并不重要。
虽然不是当今使用最广泛的编程语言,但它仍在使用。g++ 可以编译汇编代码。如果您知道自己在做什么,那么它会给您带来一定的速度优势。
关于你的问题,是的,你是对的。根据具体情况,考虑一种或另一种导致不同指令具有相同操作码的方式会有所帮助。