<转>NEG+SBB指令组合的用处

计算机中数码的表示:

定义-》

正数:原码,反码,补码相同。

负数:原码为其对应正数原码最高符号位取反。

   反码为其原码除符号位外都取反。

   补码为其原码除符号位外取反加1。

所以最高位符号位都不变。

补码机:正数补码为其原码,负数为其正数原码取反加1。

NEG指令,相当于0-OPR,并影响进位标志CF.

数学意义上相当于:相当于0-OPR

在计算时实际是以补码形式运算,运算时只有0不影响CF,其它情况都影响CF.为什么,请看以下分析:

(1)假设有数:a=3;

那么:NEG a

分析:a补码为0011,0的补码为0000,所以0000-0011最终会向高位借1所以会有CF=1

(2)假设有数:a=-3;

那么:NEG a

分析:a为负数,补码为1101,所以0000-1101=0011即正数3,所以CF=1

NEG+SBB指令

假设有C语言:
  if(foo() != 0)
  {
    return(FALSE);
  }else{
    return(TURE);
  }
也可以是:
  if(foo() != 0) return(FALSE);
  return TURE;

可以这样汇编(用fasm语法):

  call [foo];调用foo(),返回值在eax中
  neg eax;把操作数按位求反后末位加1, 且if(EAX==0){CF=0}else{CF=1}
  sbb eax,eax; eax-eax-cf ==> (eax)
        ;操作结果:如果foo的返回值不是 0,此时 (eax) = -1
        ;    :如果foo的返回值是 0,此时 (eax) = 0
  inc eax  ; 操作结果:如果foo的返回值不是 0,此时 (eax) = 0
        ;    :如果foo的返回值是 0,此时 (eax) = 1
;===============================================================================
; 进一步解释
;===============================================================================
; if (EAX)=0 则:
; NEG EAX ;等价于: 0 - (EAX) = 0 , 结果: (EAX)=0 ,CF=0
; SBB EAX, EAX ; 等价于 (EAX)-(EAX)-(CF) , 结果为: (EAX)=0
; INC EAX ; ,结果 (EAX)=1

;if EAX!=0 (假设 EAX=5) 则:
; NEG EAX 等价于: 0 - 5 = -5 所以: (EAX)= -5 ,但CF=1
; SBB EAX, EAX 等价于 (EAX)-(EAX)-(CF) 即: (EAX)= -1
; INC EAX 结果 (EAX)=0
;-------------------------------------------------------------------------------
; 以下内容来自网络:
;-------------------------------------------------------------------------------
; 问:
; mov eax,ebx //ebx此时为16位的数,只有bx有值
; neg eax
; sbb eax,eax //eax难道不为零吗?如为零,上两句有何用?
; 此时eax到底是什么值?
; 答:
; 这个主要是sbb指令的作用吧。它除了'源操作数'减去'目的操作数 '外,还得减去'进位标记位CF '。所以,
; sbb eax, eax 的结果是看之前的 CF 的状态了, 你这里就是 neg eax 了.
; neg 指令对 CF 的影响: 如果操作数为0, 则 CF=0 ; 否则, CF=1.
; 所以, 这里的 sbb 指令后 eax 中的结果应该是,
; bx = 0, EAX = 0;
; bx <> 0, EAX = -1
;------------------
; NEG、NOT指令简介
;------------------
;格式:NEG OPR ;B/W执行的操作:←求补这条指令的执行影响全部标志位。
;下面就求补操作时对CF和OF两个标志位的影响做一个分析。求补操格式:NEG OPR ;B/W

;执行的操作:←求补

;这条指令的执行影响全部标志位。

;下面就求补操作时对CF和OF两个标志位的影响做一个分析。
;求补操作即是把操作数按位求反后末位加1,即FFFFH-OPR+1=0-OPR。
;也就是说,对一个操作数求补,相当于用0减去此操作数。
;参加求补运算的操作数当然是有符号数。
;对于CF而言,只有对0求补时,CF=0,其余情况都使CF=1。
;0减去负数应该是正数,但当操作数的值是80H或8000H时,求补后其值保持不变,
;仍为负数,固产生溢出,OF=1。;其余情况都使OF=0。
;

;求反指令NOT的操作是对操作数按位求反,即FFFFH-OPR。所以假定要对AX寄存器中的操作
;数进行求补,那么可以;有如下几种方法:
;
;方法1:NEG AX
;
;方法2:NOT AX
; INC AX
;
;方法3:MOV BX,0
; XCHG AX,BX
; SUB AX,BX
;
;注意:由于求补运算的结果应在AX中,所以方法3中要使用交换指令将AX和BX互换

第一部份#include <iostream> #include <memory> #include <stack> #include <fstream> #include <vector> #include <cmath> #include <iomanip> #include <exception> #include <climits> #include <array> #include <cstdint> #include <string> using namespace std; class T { public: virtual bool isOperator() = 0; virtual ~T() {} }; class ValueToken : public T { public: long long value; long long get_value() { return value; } virtual bool isOperator() { return false; } explicit ValueToken(long long val) : value(val) {} }; class OperatorToken : public T { public: enum OpType { BGN = 0, END, ADD, MNS, NEG, MUL, DIV, POW, LBK, RBK } optr; virtual bool isOperator() { return true; } char get_char() { switch (optr) { case BGN: return '@'; case END: return '$'; case ADD: return '+'; case MNS: return '-'; case NEG: return '#'; case MUL: return '*'; case DIV: return '/'; case POW: return '^'; case LBK: return '('; case RBK: return ')'; default: return '?'; } } explicit OperatorToken(OperatorToken::OpType op) : optr(op) {} bool is_prior(const OperatorToken& r) { return prior_table[this->optr][r.optr]; } static bool prior_table[10][10]; }; bool OperatorToken::prior_table[10][10] = { //BGN, END, ADD, MNS, NEG, MUL, DIV, POW, LBK, RBK {0,0,0,0,0,0,0,0,0,0},//BGN {1,0,0,0,0,0,0,0,0,0},//END {1,1,0,0,0,0,0,0,1,0},//ADD {1,1,0,0,0,0,0,0,1,0},//MNS {1,1,1,1,0,1,1,1,1,0},//NEG {1,1,1,1,0,0,0,0,1,0},//MUL {1,1,1,1,0,0,0,0,1,0},//DIV {1,1,1,1,0,1,1,1,1,0},//POW {1,1,1,1,1,1,1,1,1,0},//LBK {1,1,0,0,0,0,0,0,1,0},//RBK };
05-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值