首页
社区
课程
招聘
[求助]mov eax, 38E38E39
发表于: 2008-7-19 16:20 34330

[求助]mov eax, 38E38E39

2008-7-19 16:20
34330

006A0200  /$  8B41 04       mov     eax, dword ptr [ecx+4]  ;  0F0C78A8
006A0203  |.  85C0          test    eax, eax
006A0205  |.  75 01         jnz     short 006A0208
006A0207  |.  C3            retn
006A0208  |>  8B49 08       mov     ecx, dword ptr [ecx+8]  ;  0F0C7938
006A020B  |.  2BC8          sub     ecx, eax
006A020D  |.  B8 398EE338   mov     eax, 38E38E39
006A0212  |.  F7E9          imul    ecx
                    ;  EAX*ECX 低位放EAX  高位放EDX
006A0214  |.  C1FA 03       sar     edx, 3                  ;  右移3位,相当于/8
006A0217  |.  8BC2          mov     eax, edx                ;  4 10
006A0219  |.  C1E8 1F       shr     eax, 1F
006A021C  |.  03C2          add     eax, edx
006A021E  \.  C3            retn

请问将mov     eax, 38E38E39 这个有什么用??


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 8
支持
分享
最新回复 (60)
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
38E38E39是常量值吧...
2008-7-19 16:35
0
雪    币: 175
活跃值: (69)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
恩,是一个常量值,不知是否有什么特别的含义,也许没有
2008-7-19 16:45
0
雪    币: 2362
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
006A0212  |.  F7E9          imul    ecx                     ;  EAX*ECX 低位放EAX  高位放EDX
都写出来了  38E38E39*ECX
2008-7-19 18:11
0
雪    币: 11705
活跃值: (975)
能力值: ( LV12,RANK:779 )
在线值:
发帖
回帖
粉丝
5
这个是编译器优化后的汇编代码,把除法优化为乘法。
实际上就是除以9.
因为:
x / 9  = ( x * 38E38E39 / 2 ^33)
2008-7-19 18:51
0
雪    币: 11705
活跃值: (975)
能力值: ( 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
2008-7-19 19:13
0
雪    币: 175
活跃值: (69)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不错,学了点东西。
2008-7-20 14:55
0
雪    币: 2362
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
厉害  佩服!
2008-7-20 15:03
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
9
挖!娃!瓦!哇!
2008-7-20 15:07
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
上面的人真强大~~~~~
2008-7-20 15:10
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
有运算规则吗
2008-7-20 15:13
0
雪    币: 11705
活跃值: (975)
能力值: ( LV12,RANK:779 )
在线值:
发帖
回帖
粉丝
12
规则就是:
除数扩大X倍得到一个2^N。
除法就变为:被除数乘以X,再右移N位了。

A/B =  AX /BX = AX >> N  

比如 除以3,
会先乘以 0xAAAAAAAB ,再移位

2008-7-20 16:56
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13

!开眼界了。。
2008-7-20 18:41
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
但是你的除以9的例子中是算术右移1次,逻辑右移31次呀,跟公式的2^33的33次右移不一样呀~
2008-7-20 19:58
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
15
这个贴,不得不拜
2008-7-21 00:04
0
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
真佩服  readyu !

膜拜一下。
2008-7-21 00:19
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
顶。强贴留名
2008-7-21 10:40
0
雪    币: 362
活跃值: (25)
能力值: ( 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。
2008-7-21 11:22
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
19
昨天找人用VC6试过了,例如除数是821的时候,就不止移33位了。这个是近似算法,只是因为整数寄存器显示不了小数,所以得出正确的答案。具体算法不明

VS2005已经没有这种“优化”了。昨天跟朋友讨论的结果是将IDIV分成这么多条指令,事实上是降低CPU效率的。

VC6有这个优化估计是因为早期CPU除法比乘法慢很多。
2008-7-21 12:01
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
学习了,顶!!
2008-7-21 14:42
0
雪    币: 200
活跃值: (10)
能力值: ( 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]
2008-7-24 10:29
0
雪    币: 200
活跃值: (10)
能力值: ( 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个字节

2008-7-24 10:31
0
雪    币: 215
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
受教了!  谢谢!
2008-7-24 10:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
由于乘法结果的高32位存在edx中,低32位存在eax中,所以取出edx就相当于把结果右移了32位,再算术右移1位,总共是33位
至于后面的逻辑右移31位,是要把MSB符号位取出来,是负数的话就把除法的结果加1

2008-7-24 10:36
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
25
还好没有了.
不然注册机会写得莫明其妙
2008-7-24 12:16
0
游客
登录 | 注册 方可回帖
返回
//