←前ページへ :  INDEX :  次へ→


3-5.減算 ( Subtraction )

  昔々の世界では、減算命令がないCPUもありました。そこで前にも 説明したように「2の補数」という概念を用いて減算を実行してきました。現在のCPUでは、どんなに安いCPUにも減算命令は用意されています。

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ビットの減算となる)

←前ページへ :  INDEX :  次へ→