我正在自己学习集会,我有一个混乱,我想清楚.
因此,根据我的理解,x86计算机使用相同的电路进行加法和减法.对于减法,将负数转换为其2补码,然后可以使用加法电路来执行减法.例如:等式4 - 2转换为4 + (-2)
因此,如果可以使用2补语进行减法,那么SUB指令的目的是什么?
lur*_*ker 10
在2的补码世界中,可以通过取1的补码(所有位反转)并加1来获得整数的否定.例如,在8位世界中:
A: 0x00000002 ; my number
~A: 0xFFFFFFFD ; 1's complement of my number
-A: 0xFFFFFFFE ; 2's complement of my number (negative A)
Run Code Online (Sandbox Code Playgroud)
要减去A-B,我们肯定可以添加负数,A+(-B):
NOT B ; invert each bit in the 8-bit value, B
ADD B, 1 ; add 1, giving the 2's complement negated B
ADD A, B
Run Code Online (Sandbox Code Playgroud)
当然B,在我添加它之前,我必须修改(否定它).如果我想B保持原状怎么办?
PUSH B ; save B
NOT B ; invert each bit in the 8-bit value, B
INC A ; add 1, giving the 2's complement negated B
ADD A, B
POP B ; restore B
Run Code Online (Sandbox Code Playgroud)
要么
NOT B ; invert each bit in the 8-bit value, B
INC A ; add 1, giving the 2's complement negated B
ADD A, B
NOT B ; restore B
Run Code Online (Sandbox Code Playgroud)
这样才行.但是只是有一个SUB指令不是更容易吗?
SUB A, B
Run Code Online (Sandbox Code Playgroud)
如果你正在编写汇编语言来做很多算术,你更喜欢哪种方法?而且,在第一种情况下,我使用了一条INC A指令.我可以在没有INC使用的情况下离开ADD A, 1.但是ADD A, 1,在许多微处理器上,要求我从指令存储器中取出更多以执行以获得立即1值.因此,INC提供了一种,因为这种操作是如此常见.
当微处理器设计者确定具有哪种指令集时,他们会考虑最常用的操作类型.减法很常见,因此SUB指令非常方便.因此,它几乎存在于您将找到的任何指令集中.指令集中还有其他指令,其存在的原因不太明显.在x86,例如,有XLAT指示,所有的"弦"的指示,LODS,STOS,等他们为什么存在时,我可以做一切工作,MOV和INC等?因为有人认为这些操作很常见,值得单一指令.
因此SUB,与CPU实现的许多其他指令一样,指令背后的目的是提供更快(执行时间)和更简单的方式来执行最常在软件中执行的操作,并与实际限制多少的事实相平衡说明可以实施.
因为它是最常见的操作之一,所以有专门的指令可以帮助提高速度.设计师知道如何快速实现,并且不需要像你想象的那样单独否定
来自着名的计算机体系结构书籍计算机组织与设计,第四版: David A. Patterson和John L. Hennessy 的硬件/软件界面以及 David Money Harris的数字设计与计算机体系结构,Sarah L. Harris我们知道MIPS设计原则如下
这些在其他架构中也是正确的.在x86和许多其他(主要是较旧的)体系结构中,由于向后兼容性,有些无法实现,但主要要点适用.
由于1 日和3 点的原则,我们需要做的指令集尽可能紧凑,不产生新的指令,如果我们可以用其它指令去做.但是,根据原则2和4,我们需要尽可能快地进行常规操作.
事实上,大多数指令都是冗余的,因为我们可以将Turing完整指令集只有一条指令.x86本身不是一个OISC架构,但它仍然可以只用一个mov或add/ 来做任何事情,sub因为它们被证明是图灵完备的.甚至还有编译器将有效的C代码编译到只有MOV的程序中(或者只有XOR,SUB,ADD,XADD,ADC,SBB,AND/OR,PUSH/POP,1位移位或CMPXCHG/XCHG)名为movfuscator
因此,add或者sub我们可以轻松获得移位,按位运算和乘法/除法.然而,这些基本操作可能需要非常长的一系列指令来模拟,用户将不满意.
这就是为什么制造商不断向新的微结构添加新指令的原因,因为新的需求会使得在开始使用之前不常见.例如,当3D应用程序成为新趋势时,他们决定为矢量和3D操作添加SIMD指令,矩阵操作也很常见.然后,当提高安全性要求使加密更加普遍时,引入了AES指令来增强加密应用程序.但这还不够,因为密码学和许多其他应用程序使用了大量的多精度算术,英特尔添加了MULX/ADOX/ADCX指令来加快这些速度.现在,您将看到加速AI操作的指令开始进入架构
回到主要问题,减法是非常常见的,因此它值得单独指令.如果没有它,你将需要negate一个操作数,然后add至少花费两倍的时间和指令空间.sub a, b比...更好neg b; add a, b.
然而减法不一定慢,因为否定的,你以为,因为设计师用巧妙的技巧,使加法器两者都做add,并sub在相同的时钟数的加入只是一个复用器与新的输入一起与非门Binvert以有条件地反转第二个输入如下
基本它的工作方式实现,在补-b = ~b + 1,所以a - b = a + ~b + 1.这意味着我们只需要将进位设置为1(或者取消进位的进位)并反转第二个输入.
我在开头提到的书中也提到过这种类型的ALU.不幸的是,由于授权问题,我无法引用它,但我在教授的另一本书中找到了.帕特森和教授.轩尼诗:
正如您所看到的,通过另一个非常简单的修改,他们现在可以使用单个ALU执行6种不同的操作:add,sub,slt,和,或者,
您可以在ALU设计课程中找到更多信息,也可以在Google上找到关键字Binvert/Bnegate的更多信息