Assembly 避免使用条件分支

2018-10-28 10:08 更新

现代处理器使用了非常尖端的技术来尽可能快地执行代码。一个普遍技术称为预测执行。这种技术使用CPU的并行处理能力来同时执行多条指令。条件分支与这项技术有冲突。一般说来,处理器是不知道分支是否会执行。如果执行了,跟没有执行相比执行的是一组不同的指令。处理器试着预测分支是否执行。如果预测错误,处理器就浪费了它的时间去执行了一些错误的代码。


用ADC计算位数


一个避免这个问题的办法就是如果可能尽量避免使用条件分支。在以前的例子中,EAX寄存器中的值为\on"的位被计算出来。它使用了一个分支跳转到INC指令。图3.3展示了如何使用ADC指令直接加上进位标志位来替代这
个分支。


SETxx 指令提供了在一定情况下替换分支的方法。基于FLAGS寄存器的状态,这些指令将一个字节的寄存器或内存空间中的值置为0或1。在SET后的字符与条件分支使用的是一样的。如果SETxx 条件为真,那么储存的结果就为1,如果为假,则储存的结果就为0。例如:


setz      al             ; AL = 如果ZF标志位置位了则为1,否则为0。


使用这些指令,你可以开发出一些进行数值运算的精巧的技术,而不需要使用分支。


例如,考虑查找两个数的最大数的问题。这个问题的标准解决方法是使用一条CMP指令再使用条件分支对最大值进行操作。下面这个例子展示了不使用分支如何找到最大值。


实例1

实例2


这个诀窍是产生一个可以用来选择出正确的最大值的俺码。在30行的SETG指令如果第二个输入值是最大值就将BL置为1,否则就置为0。这
不是真正需要的掩码。为了得到真正需要的掩码,31行对整个EBX寄存器使用了NEG指令。(注意:EBX在前面已经置为0了。)如果EBX等于0,那
么这条指令就不做任何事情;但是如果EBX为1,结果就是-1的补码表示或0xFFFFFFFF。这正好是需要的位掩码。剩下的代码就是使用这个位掩
码来选择出正确的输入的最大值。


另外一个可供选择的诀窍是使用DEC语句。在上面的代码中,如果用DEC代替NEG,那么结果同样会是0或0xFFFFFFFF。但是,与使用NEG相比,得到值将是反过来的。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号