- 注册时间
- 2010-10-22
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 2292
- 在线时间
- 小时
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?欢迎注册
×
大家都来说说吧.........,我看到哪,说到哪......
一.消除、减少分支的数量
通过应用setcc指令或奔腾处理器的条件转移指令(CMOV 或 FCMOVE)来削除分支。
比如下面这个c语言的例子:- ebx = (A < B) ? CONST1 : CONST2;
复制代码 上面这个代码条件比较两个值,A 和 B. 如果为真(A- cmp A, B ; condition
- jge L30 ; conditional branch
- mov ebx, CONST1
- jmp L31 ; unconditional branch
- L30:
- mov ebx, CONST2
- L31:
复制代码对于上面的汇编,我们可以用setcc指令来替换jge,消除分支,以达到优化的目的,程序如下:- xor ebx, ebx ;clear ebx
- cmp A, B
- setge bl ;When ebx = 0 or 1
-
- ;OR the complement condition
- dec ebx ;ebx=00...00 or 11...11
- and ebx, (CONST2-CONST1) ;ebx=0 or(CONST2-CONST1)
- add ebx, min(CONST1,CONST2) ;ebx=CONST1 or CONST2
复制代码 注意一点,min(CONST1,CONST1)由常量CONST1,CONST2已定,比如min(6,8)=6;
当abs(CONST1-CONST2)为1,2,4,8时,另一种有趣的实现如下:- xor ebx, ebx
- mov eax, A
- cmp eax, B
- setge bl
- lea ebx, [ebx*(CONST2-CONST1)+CONST1]
复制代码 部分机器码如下:- ;=======================================================
- 00401000 >/\$ A1 00304000 MOV EAX,DWORD PTR DS:[403000]
- 00401005 |. 3B05 04304000 CMP EAX,DWORD PTR DS:[403004]
- 0040100B |. 7D 07 JGE SHORT good.00401014
- 0040100D |. BB 06000000 MOV EBX,6
- 00401012 |. EB 05 JMP SHORT good.00401019
- 00401014 |> BB 0E000000 MOV EBX,0E
- ;=======================================================
- 00401028 |. 33DB XOR EBX,EBX
- 0040102A |. A1 00304000 MOV EAX,DWORD PTR DS:[403000]
-
- 0040102F |. 3B05 04304000 CMP EAX,DWORD PTR DS:[403004]
-
- 00401035 |. 0F9CC3 SETL BL
- 00401038 |. 4B DEC EBX
- 00401039 |. 83E3 08 AND EBX,8
-
- 0040103C |. 83C3 06 ADD EBX,6
- ;=======================================================
- 0040104E |. 33DB XOR EBX,EBX
- 00401050 |. A1 00304000 MOV EAX,DWORD PTR DS:[403000]
-
- 00401055 |. 3B05 04304000 CMP EAX,DWORD PTR DS:[403004]
- 0040105B |. 0F9DC3 SETGE BL
- 0040105E |. 8D1CDD 06000000 LEA EBX,DWORD PTR DS:[EBX*8+6]
- ;=======================================================
复制代码 再细化,比如对于上面的程序块,通过填充其他指令或nop,实现对齐,以达到性能峰值。
特别是对于核心模块。- xor ebx, ebx ;clear ebx
- mov eax,A
- cmp eax, B
- setl bl ;When ebx = 0 or 1
- ;OR the complement condition
- dec ebx ;ebx=00...00 or 11...11
- and ebx, (CONST2-CONST1) ;ebx=0 or(CONST2-CONST1)
- add ebx, CONST1 ;ebx=CONST1 or CONST2
复制代码 做到8字节对齐:- xor ebx, ebx ;clear ebx
- mov eax,A
- nop
- nop
- cmp eax, B
- setl bl ;When ebx = 0 or 1
- ;OR the complement condition
- dec ebx ;ebx=00...00 or 11...11
- and ebx, (CONST2-CONST1) ;ebx=0 or(CONST2-CONST1)
- nop
- add ebx, CONST1 ;ebx=CONST1 or CONST2
复制代码 //-----------------------------------------------------
第二种方法是用"新"的指令CMOV,FCMOV来消除分支
比如测试ecx是否为0- test ecx,ecx
- jne L20
- mov eax,ebx
- L20:
复制代码 可以换成:- test ecx, ecx ; test the flags
- cmoveq eax, ebx ; if the equal flag is set, move ebx to eax
- L20:
复制代码 指令参考:http://www.cnblogs.com/itjin45/archive/2009/09/03/1559129.html
测试程序:- .386
- .model flat,stdcall
-
- include user32.inc
- include kernel32.inc
- include msvcrt.inc
-
- includelib user32.lib
- includelib kernel32.lib
- includelib msvcrt.lib
-
- CONST1 equ 6
- CONST2 equ 14 ;7,8,10,14
-
- .data
- A dd 5 ;10
- B dd 7
- fmt db ' %d',0
-
- szPause db 'Pause',0
-
-
- .code
- ;****************************
- start:
- ;----------------------------
- ;ebx = (A < B) ? CONST1 : CONST2;
- ;**********法一**************
- mov eax,A
- cmp eax,B
- jge L30
- mov ebx,CONST1
- jmp L31
- L30:
- mov ebx,CONST2
- L31:
- invoke crt_printf,offset fmt,ebx
- ;**********法二**************
- xor ebx, ebx ;clear ebx
- mov eax,A
- cmp eax, B
- setl bl ;When ebx = 0 or 1
- ;OR the complement condition
- dec ebx ;ebx=00...00 or 11...11
- and ebx, (CONST2-CONST1) ;ebx=0 or(CONST2-CONST1)
- add ebx, CONST1 ;ebx=CONST1 or CONST2
-
- invoke crt_printf,offset fmt,ebx
-
- ;**********法三**************
- xor ebx, ebx
- mov eax, A
- cmp eax, B
- setge bl ; or the complement condition
- lea ebx, [ebx*(CONST2-CONST1)+CONST1]
-
- invoke crt_printf,offset fmt,ebx
-
-
-
- invoke crt_system,offset szPause
- invoke ExitProcess,0
-
- end start
复制代码 |
|