neg eax sbb eax, eax
今天下午看一个反汇编的代码,并试图跟源代码对上号。
下面的语句组合让我非常费解,花了好久才弄清楚。贴出来,供大家参考。
neg r
sbb r, r
and r, (val1 - val2)
add r, val2
neg r 指令的结果是设置Carry Flag, 也就是借位的标志位. 因为neg r的操作语义是0 - r, 零减去任何非零的数,都会产生"借位"的. 当然这里r寄存器中的值也被改掉了,不过没关系, 反正它都要被稍后的指令再改掉的.
紧接着,sbb r, r 指令设置r为零或者-1. 因为语义为用一个值去减掉它自身, 结果当然是零啰. 但是,这样做会把carry flag一起给减掉的, 该指令的公式是
r – r – CF –> r
所以,如果r最开始就是0, 那么sbb r, r的结果是将r设置为0. 如果不是零,那么结果是0-CF = 0-1 = –1 = FFFFFFFF
第三个操作是一个mask的操作, 如果r是0的话,任何数与0做与操作都是0. 如果r不是0, 那么任何数与FFFFFFFF做与操作,都会留下那个值.
也就是说, 如果r是0, 那么r为0; 如果不为0, 那么结果为val1 – val2.
第四个操作是把val2加到r上,结合之前的结论, 我们可以得出
如果r是0, 那么结果等于val2, 如果r不是0, 那么结果等于val1 – val2 + val2, 结果为val1.
总结一下,整个四句指令一起的意思就是, 如果r为0, 那么r中的值为val2, 如果r不为0, 那么r中的值会是val1. 即
r ? val1 : val2