好友
阅读权限10
听众
最后登录1970-1-1
|
Snow
发表于 2012-6-22 14:20
Debug版本的除法优化比较简单,我也不多说些什么了,重点看注释吧下面汇编代码中只有从地址0040108C 开始的代码才有优化,上面的是 普通除法,可略过。
C:
#include <stdio.h>
#include <stdlib.h>void main(int argc)
{
printf("03=%d",argc/3); //-*
printf("05=%d",argc/5); // |
printf("11=%d",argc/11); // |
printf("59=%d",argc/59); //-*
printf("04=%d",argc/4);
printf("64=%d",argc/64);
}ASM:00401010 >|> \55 push ebp
00401011 |. 8BEC mov ebp,esp
00401013 |. 83EC 40 sub esp,0x40
00401016 |. 53 push ebx
00401017 |. 56 push esi
00401018 |. 57 push edi
00401019 |. 8D7D C0 lea edi,[local.16]
0040101C |. B9 10000000 mov ecx,0x10
00401021 |. B8 CCCCCCCC mov eax,0xCCCCCCCC
00401026 |. F3:AB rep stos dword ptr es:[edi]
00401028 |. 8B45 08 mov eax,[arg.1] ; eax=被除数
0040102B |. 99 cdq
0040102C |. B9 03000000 mov ecx,0x3 ; ecx=3(除数)
00401031 |. F7F9 idiv ecx
00401033 |. 50 push eax ; /<%d>
00401034 |. 68 44204200 push Debugasm.00422044 ; |format = "03=%d"
00401039 |. E8 D2000000 call Debugasm.printf ; \printf
0040103E |. 83C4 08 add esp,0x8
00401041 |. 8B45 08 mov eax,[arg.1] ; eax=被除数
00401044 |. 99 cdq
00401045 |. B9 05000000 mov ecx,0x5 ; ecx=除数(5)
0040104A |. F7F9 idiv ecx
0040104C |. 50 push eax ; /<%d>
0040104D |. 68 3C204200 push Debugasm.0042203C ; |format = "05=%d"
00401052 |. E8 B9000000 call Debugasm.printf ; \printf
00401057 |. 83C4 08 add esp,0x8
0040105A |. 8B45 08 mov eax,[arg.1] ; eax=被除数
0040105D |. 99 cdq
0040105E |. B9 0B000000 mov ecx,0xB ; ecx=除数(11)
00401063 |. F7F9 idiv ecx
00401065 |. 50 push eax ; /<%d>
00401066 |. 68 34204200 push Debugasm.00422034 ; |format = "11=%d"
0040106B |. E8 A0000000 call Debugasm.printf ; \printf
00401070 |. 83C4 08 add esp,0x8
00401073 |. 8B45 08 mov eax,[arg.1] ; eax=被除数
00401076 |. 99 cdq
00401077 |. B9 3B000000 mov ecx,0x3B ; ecx=除数(59)
0040107C |. F7F9 idiv ecx
0040107E |. 50 push eax ; /<%d>
0040107F |. 68 2C204200 push Debugasm.0042202C ; |format = "59=%d"
00401084 |. E8 87000000 call Debugasm.printf ; \printf
00401089 |. 83C4 08 add esp,0x8 ; 上面的除法运算均无优化(就是说下面的都有。。)
; 上面的除法运算均无优化(就是说下面的都有。。)
; 上面的除法运算均无优化(就是说下面的都有。。)
; 上面的除法运算均无优化(就是说下面的都有。。)
; 上面的除法运算均无优化(就是说下面的都有。。)
0040108C |. 8B45 08 mov eax,[arg.1] ; eax=被除数
0040108F |. 99 cdq ; eax是正则edx=0 否则 edx=FFFFF……(32个F)
00401090 |. 83E2 03 and edx,0x3 ; eax是正数则什么都不做(因为edx(值为0)跟任何数AND都是0) eax是负数的话,就取除数-1
00401093 |. 03C2 add eax,edx ; 用"除数-1"跟被除数相加
00401095 |. C1F8 02 sar eax,0x2 ; 然后右移2位(除以4) 以上代码可得出 被除数除以除数的结果(根据公式.....)
也不说什么公式了,看下下面这些式子的规律吧:
-16/4 = (-16+3)>>2 = -13>>2 = -4
-5/4 = (-5+3) >>2 = -2 >>2 = -1
-4/4 = (-4+3) >>2 = -1 >>2 = -1
-3/4 = (-3+3) >>2 = 0 >>2 = 0
-2/4 = (-2+3) >>2 = 1 >>2 = 0
这里是有公式在里面的,在<<C++反汇编技术揭秘>>一书中有提及证明方法。
00401098 |. 50 push eax ; /<%d>
00401099 |. 68 24204200 push Debugasm.00422024 ; |format = "04=%d"
0040109E |. E8 6D000000 call Debugasm.printf ; \printf
004010A3 |. 83C4 08 add esp,0x8
004010A6 |. 8B45 08 mov eax,[arg.1]
004010A9 |. 99 cdq
004010AA |. 83E2 3F and edx,0x3F
004010AD |. 03C2 add eax,edx
004010AF |. C1F8 06 sar eax,0x6
004010B2 |. 50 push eax ; /<%d>
004010B3 |. 68 1C204200 push Debugasm.0042201C ; |format = "64=%d"
004010B8 |. E8 53000000 call Debugasm.printf ; \printf
004010BD |. 83C4 08 add esp,0x8
004010C0 |. 5F pop edi
004010C1 |. 5E pop esi
004010C2 |. 5B pop ebx
004010C3 |. 83C4 40 add esp,0x40
004010C6 |. 3BEC cmp ebp,esp
004010C8 |. E8 C3000000 call Debugasm._chkesp
004010CD |. 8BE5 mov esp,ebp
004010CF |. 5D pop ebp
004010D0 \. C3 retn
|
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|