惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
Jina AI
Jina AI
Hugging Face - Blog
Hugging Face - Blog
A
About on SuperTechFans
Y
Y Combinator Blog
D
DataBreaches.Net
I
InfoQ
Recent Announcements
Recent Announcements
Last Week in AI
Last Week in AI
G
Google Developers Blog
博客园_首页
博客园 - 司徒正美
V
V2EX
Stack Overflow Blog
Stack Overflow Blog
博客园 - 叶小钗
Engineering at Meta
Engineering at Meta
Apple Machine Learning Research
Apple Machine Learning Research
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
B
Blog
MongoDB | Blog
MongoDB | Blog
博客园 - 【当耐特】
D
Docker
量子位

博客园 - woodfish

偏序集的Dilworth定理 XJOJ历经2个月终于完成啦~~ fork()调用的一个趣题 实现google那种输入框提示的功能 POJ 3691 安徽第二题 有限状态自动机+DP 哈尔滨赛区网络预选赛总结 [计算几何]点集中的点能组成多少个正方形 [计算几何]POJ 1375 点对圆的切线+线段重叠 [计算几何]POJ 1556 判断线段相交+Dijkstra [计算几何] POJ 1873 暴力+凸包 [计算几何]POJ 1266 三角形的外接圆 圆的参数方程 POJ 1026 置换群 [计算几何]POJ 1031 计算点对多边形的偏转角度 [计算几何]POJ2079 求点集中面积最大的三角形 [计算几何]POJ3608 求2个不相交凸包的最短距离 [计算几何]凸包的旋转卡壳算法 C++禁止一个类被继承的技术 C与汇编的接口技术 计算位数的3种方法
避免使用条件分支
woodfish · 2008-02-28 · via 博客园 - woodfish

现代处理器使用了非常尖端的技术来尽可能快的执行代码。一个普遍的技术称为预测执行。这种技术使CPU的并行处理能力来同时执行多条指令。条件分支与这项技术有冲突。一般来说,处理器是不知道分支是否会执行。
一个避免这个问题的方法就是如果可能尽量避免使用条件分支。在计算eax中比特位为1的例子中,一般会用一个分支跳转到INC指令(检查CF标志),下面展示了如何使用ADC指令直接加上进位标志来替代这个分支。

    mov bl,0
    
mov ecx,32
count_loop:
    
shl eax,1
    
adc bl,0
    loop count_loop

Setxx指令提供了在一定情况下替换条件分支的方法。基于FLAGS寄存器的状态,这些指令将一个字节的寄存器或内存空间的值置为0或1.在SET后的字符与条件分支使用的是一样的。如果SETxx条件为真,那么储存的结果就是1,如果为假,则储存的结果就为0.例如
setz al   ;AL=如果ZF标志置位了则为1,否则为0
例如,考虑查找两个数的最大数的问题。这个问题的标准解决方法是使用一条CMP指令再使用条件分支对最大值进行操作。下面这个例子展示了不使用分支如何找到最大值。

%include "asm_io.inc"

segment .data
message1    db    
"Enter a number: ",0
message2    db    
"Enter another number: ",0
message3    db    
"The larger number is: ",0

segment .bss
input1    resd    
1

segment .text
    global _asm_main
_asm_main:
    
enter 0,0
    
pusha

    
mov eax,message1
    
call print_string
    
call read_int
    
mov [input1],eax

    
mov eax,message2
    
call print_string
    
call print_nl

    
xor ebx,ebx
    
cmp eax,[input1]
    
setg bl        ;ebx=(input2>input1)?1:0
    neg ebx        ;ebx=(input2>input1)?0xFFFFFFFF:0
    mov ecx,ebx    ;ecx=(input2>input1)?0xFFFFFFFF;0
    and ecx,eax    ;ecx=(input2>input1)?input2:0
    not ebx        ;ebx=(input2>input1)?0:0xFFFFFFFF
    and ebx,[input1];ebx=(input2>input1)?0:input1
    or ecx,ebx    ;ecx=(input2>input1)?input2:input1

    
mov eax,message3
    
call print_string
    
mov eax,ecx
    
call print_int
    
call print_nl

    
popa
    
mov eax,0
    
leave
    
ret

这个诀窍就是产生一个可以用来选择出正确的最大值的掩码。另外一个可供选择的诀窍是使用DEC指令。在上面的代码中,如果用DEC代替NEG,那么结果同样是0或0xFFFFFFFF。但是,与使用NEG相比,得到值将是反过来的。