1

我知道要进行减法运算,您应该对第二个数字进行 2 的补码转换。是否有专门的硬件来检查 MSB,如果发现它是 1,它会进行转换吗?

另外,这个系统是否用于浮点减法?

4

3 回答 3

2

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()中,从而更难看到。)

于 2011-06-06T04:46:46.810 回答
0

看,你不必检查号码。如果 number 是 -ve 它以 2 的补码形式存储在内存中。而且您正在使用该数字 CPU 会将数字更改为您的计算本身。你不需要检查任何东西。你必须执行操作

于 2011-06-06T04:38:25.357 回答
-1

没有也没有。

转换由在 CPU 上运行的代码完成。

于 2011-06-06T04:35:13.943 回答