SUB ( Subtract ) :減算
SUB DEST,SRC 動作:DEST←DEST-SRC 影響を受けるフラグ:OF,SF,ZF,AF,CF,PF DEST:レジスタ、メモリー SRC :レジスタ、メモリー、即値(ただしメモリー、メモリーの組み合わせは除く)
SBB ( Subtract with Borrow ) :ボローも含めて減算
SBB DEST,SRC 動作:DEST←DEST-SRC-CF 影響を受けるフラグ:OF,SF,ZF,AF,CF,PF DEST:レジスタ、メモリー SRC :レジスタ、メモリー、即値(ただしメモリー、メモリーの組み合わせは除く)
減算命令も加算命令と同様にキャリーフラグを考慮する「SBB」と考慮しない「SUB」の2つの命令が用意されている。
「SUB」命令では、DEST(引かれる数)がSRC(引く数)より小さく結果がマイナスになる場合は加算と逆に、桁を借りてくる。我々が日常計算する場合、引かれる数の方が小さいと、とりあえず大きい方から小さい方を引いて、頭にマイナスをつける。例えば、「5-10」は引かれる数の方が小さいので、とりあえず大きい数(10)から小さい数(5)を引いて、マイナスをつけ「-5」とする。
アセンブラの場合はもう1桁増やし、その桁が1であると仮定して計算する。例えば、「5Bh-85h」を計算すると、図のようになる。引かれる数(5Bh)の方が小さいので、さらに1桁上に「1」があると仮定して、15Bh-85h=D6hとなる。この場合、桁借りをしたのでキャリーフラグが1になる。(OF=0,SF=1,ZF=0,他のフラグは省略)
「SBB」命令では、キャリーフラグが1ならば、さらに1を引く。すなわち前の引き算の結果、桁借りを起こしていたら、その分も引くことになり、「ADD」命令の後に、「ADC」命令を実行したのと同様に、「SUB」命令後必要ならば「SBB」命令を行う。
「SUB」「SBB」どちらも、フラグは同様に変化し、キャリーフラグは今説明した通りである。ZFは減算の結果が0であればZF=1、それ以外ならZF=0になる。
符号付き整数の減算を考えた場合、80h(-127)-1=7Fh(+127)となり、引き算をしたはずなのに、結果が大きくなってしまった場合に、オーバーフローを起こしたと言い、オーバーフローフラグOF=1となる。オーバーフローを起こさなかった場合には0になる。符号なし整数の場合はOFは無視して構わない。
符号なし、符号付き整数のどちらも計算結果の上位1bitが1ならばSF=1、上位1bitが 0ならばSF=0となる。そのほかのフラグについては省略する。
【用例】
MOV EAX,[SRC1] ;>メモリ上の64ビット数値1の下位32ビットを取得します。 SUB EAX,[SRC2] ;>メモリ上の64ビット数値2の下位32ビットを減算します。 MOV [DEST],EAX ;>結果の下位32ビットをメモリ上の結果に保存します。 MOV EAX,[SRC1+4] ;>メモリ上の64ビット数値1の上位32ビットを取得します。 SBB EAX,[SRC2+4] ;>メモリ上の64ビット数値2の上位32ビット(もしあれば下位からの桁下げ)を減算します。 MOV [DEST+4],EAX ;>結果の上位32ビットをメモリ上の結果に保存します。(この結果、64ビットの減算となる)