我知道要进行减法运算,您应该对第二个数字进行 2 的补码转换。是否有专门的硬件来检查 MSB,如果发现它是 1,它会进行转换吗?
另外,这个系统是否用于浮点减法?
我知道要进行减法运算,您应该对第二个数字进行 2 的补码转换。是否有专门的硬件来检查 MSB,如果发现它是 1,它会进行转换吗?
另外,这个系统是否用于浮点减法?
Two's Complement 运算在大多数语言中都使用一元运算-
符实现。它仅用于有符号整数类型。它可以在 ALU 中实现为不同的求反(例如NEG
)指令,也可以滚动到另一个操作中,例如,当您使用减法(例如SUB
)指令而不是加法(例如ADD
)指令时。
您的第一个问题不清楚,因为“最后一位”可以指最高有效位(MSB)或最低有效位(LSB)。在有符号整数中,MSB 表示符号;检查否定通常是作为N
条件代码寄存器中的位来实现的,该位是根据最后执行的指令的结果更新的(尽管有几条指令不会更改条件代码寄存器)。仅当原始数字为负数时才计算二进制补码是绝对值(例如ABS
)运算。检查 LSB 只会告诉您整数是偶数还是奇数。
浮点数使用单独的符号位,因此0
和-0
是不同的值。二的恭维不适用于浮点值;必须使用不同的方法。
编辑:一个例子。考虑以下 C 代码:
#include <stdlib.h>
int do_math(int a, int b)
{
return a - b;
}
int main(int argc, char* const argv[])
{
if(argc < 2)
return 0;
return do_math(atoi(argv[1]), atoi(argv[2]));
}
这可以运行:
$ gcc -O0 foo.c -o foo
$ ./foo 20 10; echo $?
10
在 x86_64 上,该函数do_math()
包含以下代码:
_do_math:
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -8(%rbp), %edx
movl -4(%rbp), %eax
subl %edx, %eax
leave
ret
前两行是序言,为函数设置堆栈。接下来的四行从堆栈中获取输入参数(因为优化被禁用,参数没有在寄存器中传递)。
然后是关键指令:subl
,它接受第二个参数( x86 的扩展 AX 寄存器,大小为 32 位)并从第一个参数( x86 的扩展 DX 寄存器,大小也是 32 位%eax
)中减去它,将结果存储回来%edx
进入%edx
. 在 ALU 中,subl
指令按原样获取第一个参数并添加第二个参数的二进制补码。它通过反转第二个参数的位(类似于~
C 中的运算符)来计算二进制补码,然后使用专用的加法器加 1。这一步可以是管道,可以对其进行优化,以便在一个周期内完成它和最终的加法,或者他们可以更进一步,将二进制补码逻辑滚动到 ALU 的加法器链中。
最后两行清理堆栈并返回。(x86 调用约定将结果存储在%edx
.
编辑 2:使用-S
选项gcc
生成程序集文件(与输入文件同名,但.c
后缀替换为.s
)。例如:(gcc -O0 foo.c -S
如果我没有用 关闭优化器-O0
,整个do_math()
函数可能会被内联到main()
中,从而更难看到。)
看,你不必检查号码。如果 number 是 -ve 它以 2 的补码形式存储在内存中。而且您正在使用该数字 CPU 会将数字更改为您的计算本身。你不需要检查任何东西。你必须执行操作
没有也没有。
转换由在 CPU 上运行的代码完成。