減算を行うには、2の補数を2番目の数値に変換する必要があることを理解しています。MSBをチェックするための専用ハードウェアはありますか?それが1であることが判明した場合、変換を実行しますか?
また、このシステムは浮動小数点の減算に使用されていますか?
減算を行うには、2の補数を2番目の数値に変換する必要があることを理解しています。MSBをチェックするための専用ハードウェアはありますか?それが1であることが判明した場合、変換を実行しますか?
また、このシステムは浮動小数点の減算に使用されていますか?
2の補数演算は、ほとんどの言語で単項演算子を使用して実装され-
ます。符号付き整数型でのみ使用されます。これは、ALUで、個別の否定(eg NEG
)命令として実装することも、別の演算にロールインすることもできます。たとえば、加算(eg SUB
)命令の代わりに減算(eg)命令を使用する場合ですADD
。
「最後のビット」は最上位ビット(MSB)または最下位ビット(LSB)のいずれかを指す可能性があるため、最初の質問は不明確です。符号付き整数では、MSBは符号を示します。負のチェックは通常N
、最後に実行された命令の結果から更新される条件コードレジスタのビットとして実装されます(ただし、いくつかの命令は条件コードレジスタを変更しません)。元の数が負の場合にのみ2の補数を計算するのは、絶対値(eg ABS
)演算です。LSBをチェックすると、整数が偶数か奇数かがわかります。
浮動小数点数は別個の符号ビットを使用するため0
、と-0
は別個の値です。Twoの補数は、浮動小数点値では機能しません。別のアプローチを使用する必要があります。
編集:例。次の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
最初の2行はプリアンブルで、関数のスタックを設定します。次の4行は、スタックから入力パラメーターをフェッチします(最適化が無効になっているため、パラメーターはレジスターに渡されませんでした)。
次に、キー命令:subl
。に。ALUでは、命令は最初のパラメーターをそのまま取得し、2番目のパラメーターの2の補数を追加します。2番目のパラメーターのビットを反転して(Cの演算子と同様)、専用の加算器を使用して1を加算することにより、2の補数を計算します。このステップはパイプラインである可能性があり、最適化して、1サイクルで完了するようにすることができます。 、またはさらに一歩進んで、2の補数ロジックをALUの加算器チェーンにロールインすることもできます。%eax
%edx
%edx
subl
~
最後の2行は、スタックをクリーンアップして戻ります。(x86呼び出し規約は、結果をに格納し%edx
ます。
編集2:-S
オプションを使用してアセンブリファイルを生成します(接尾辞がに置き換えられることをgcc
除いて、入力ファイルと同じ名前)。例:(オプティマイザーをでオフにしなかった場合、関数全体がにインライン化され、見づらくなる可能性があります。).c
.s
gcc -O0 foo.c -S
-O0
do_math()
main()
ほら、あなたは今までに番号をチェックする必要はありません。数値が-veの場合、2の補完形式でメモリに格納されます。そして、あなたはその数を使用していますCPUはあなたの計算自体に数を変更します。何もチェックする必要はありません。操作を実行する必要があります
いいえ、いいえ。
変換は、CPUで実行されているコードによって実行されます。