能力值:
( LV2,RANK:10 )
|
-
-
2 楼
38E38E39是常量值吧...
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
恩,是一个常量值,不知是否有什么特别的含义,也许没有
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
006A0212 |. F7E9 imul ecx ; EAX*ECX 低位放EAX 高位放EDX
都写出来了 38E38E39*ECX
|
能力值:
( LV12,RANK:779 )
|
-
-
5 楼
这个是编译器优化后的汇编代码,把除法优化为乘法。
实际上就是除以9.
因为:
x / 9 = ( x * 38E38E39 / 2 ^33)
|
能力值:
( LV12,RANK:779 )
|
-
-
6 楼
来个VC 6的例子:
#include <stdio.h>
int main()
{
int a;
int b;
b = rand();
a = b/9;
printf("b = %d, a= %d", b , a);
getchar();
}
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char *envp)
.text:00401000 _main proc near ; CODE XREF: start+AFp
.text:00401000 E8 0E 02 00 00 call _rand
.text:00401005 8B C8 mov ecx, eax
.text:00401007 B8 39 8E E3 38 mov eax, 38E38E39h
.text:0040100C F7 E9 imul ecx
.text:0040100E D1 FA sar edx, 1
.text:00401010 8B C2 mov eax, edx
.text:00401012 C1 E8 1F shr eax, 1Fh
.text:00401015 03 D0 add edx, eax
.text:00401017 52 push edx
.text:00401018 51 push ecx
.text:00401019 68 30 70 40 00 push offset ??_C@_0O@DGOM@b?5?$DN?5?$CFd?0?5a?$DN?5?$CFd?$AA@ ; "b = %d, a= %d"
.text:0040101E E8 BF 01 00 00 call _printf
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
不错,学了点东西。
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
厉害 佩服!
|
能力值:
( LV9,RANK:490 )
|
-
-
9 楼
挖!娃!瓦!哇!
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
上面的人真强大~~~~~
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
有运算规则吗
|
能力值:
( LV12,RANK:779 )
|
-
-
12 楼
规则就是:
除数扩大X倍得到一个2^N。
除法就变为:被除数乘以X,再右移N位了。
A/B = AX /BX = AX >> N
比如 除以3,
会先乘以 0xAAAAAAAB ,再移位
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
哇
!开眼界了。。
|
能力值:
( LV2,RANK:10 )
|
-
-
14 楼
但是你的除以9的例子中是算术右移1次,逻辑右移31次呀,跟公式的2^33的33次右移不一样呀~
|
能力值:
(RANK:570 )
|
-
-
15 楼
这个贴,不得不拜
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
真佩服 readyu !
膜拜一下。
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
顶。强贴留名
|
能力值:
( LV7,RANK:100 )
|
-
-
18 楼
我觉得以上问题主要在于38E38E39这个值,原理是z = x/y = x*(1/y)。其中1/y是编译器自己算好加入代码。公式是x=(uint64(z)*M)>>33 ,其中M的计算公式为M=((1<<33)+1)/y 比如y=9的时候 200000001/ 9 = 38E38E39。
|
能力值:
(RANK:570 )
|
-
-
19 楼
昨天找人用VC6试过了,例如除数是821的时候,就不止移33位了。这个是近似算法,只是因为整数寄存器显示不了小数,所以得出正确的答案。具体算法不明
VS2005已经没有这种“优化”了。昨天跟朋友讨论的结果是将IDIV分成这么多条指令,事实上是降低CPU效率的。
VC6有这个优化估计是因为早期CPU除法比乘法慢很多。
|
能力值:
( LV2,RANK:10 )
|
-
-
20 楼
学习了,顶!!
|
能力值:
( LV2,RANK:10 )
|
-
-
21 楼
《加密与解密》这本书里整数的除法那一章有讲这个
[QUOTE=davidcui;483454]006A0200 /$ 8B41 04 mov eax, dword ptr [ecx+4] ; 0F0C78A8
006A0203 |. 85C0 test eax, eax
006A0205 |. 75 01 jnz...[/QUOTE]
|
能力值:
( LV2,RANK:10 )
|
-
-
22 楼
顺便贴一下minimize size选项下的汇编:
00401000 push esi
00401001 call _rand (0040105c)
00401006 mov ecx,eax
00401008 push 9
0040100A cdq
0040100B pop esi
0040100C idiv eax,esi
0040100E push eax
0040100F push ecx
00401010 push offset string "b = %d, a= %d\n" (00407030)
00401015 call _printf (00401021)
0040101A add esp,0Ch
0040101D xor eax,eax
0040101F pop esi
00401020 ret
maximize speed下的是
00401000 call _rand (0040106b)
00401005 mov ecx,eax
00401007 mov eax,38E38E39h
0040100C imul ecx
0040100E sar edx,1
00401010 mov eax,edx
00401012 shr eax,1Fh
00401015 add edx,eax
00401017 push edx
00401018 push ecx
00401019 push offset string "b = %d, a= %d\n" (00407030)
0040101E call _printf (00401030)
00401023 add esp,0Ch
00401026 xor eax,eax
00401028 ret
minimize下由于用idiv指令,节省了8个字节
|
能力值:
( LV2,RANK:10 )
|
-
-
23 楼
受教了! 谢谢!
|
能力值:
( LV2,RANK:10 )
|
-
-
24 楼
由于乘法结果的高32位存在edx中,低32位存在eax中,所以取出edx就相当于把结果右移了32位,再算术右移1位,总共是33位
至于后面的逻辑右移31位,是要把MSB符号位取出来,是负数的话就把除法的结果加1
|
能力值:
( LV9,RANK:180 )
|
-
-
25 楼
还好没有了.
不然注册机会写得莫明其妙
|
|
|