首页
社区
课程
招聘
[原创]浅谈sar指令在整数除法中的优化
发表于: 2010-2-9 10:42 14315

[原创]浅谈sar指令在整数除法中的优化

2010-2-9 10:42
14315

初学《加密与解密3》看到第四章里的编译器的算法优化时的一点困惑,然后动手实践了一下得到一点心得体会,拿来跟大家分享!
   ps.本人汇编基础非常差,sar指令也是刚刚学会的,另外脑袋转的慢,别人用5分钟能解决的问题,我得用10分钟,因此这篇文章我花了6个多小时才完成。
如果有错误欢迎指出,以免误导他人!

浅谈Sar指令在整数除法中的优化

还不懂sar指令的同学马上去baidu啊,Google啊查去,我刚查完!
首先来看一段vc代码

int get()
{
  return -8;
}

int main()
{
  int a = get()/2;
  printf("%d",a);
  return 0;
}
00401000  /$  B8 F8FFFFFF   mov     eax, -8   ; get子程序 总是返回-8
00401005  \.  C3            retn
00401006      90            nop
00401010  /$  E8 EBFFFFFF   call    00401000  ;得到返回值 eax = -8
00401015  |.  99            cdq                ;将eax的值符合扩展到edx
00401016  |.  2BC2          sub     eax, edx   ;等价于 eax = eax + 符号位(eax为正数或者0时符号位为0,负数时为1)
00401018  |.  D1F8          sar     eax, 1      ;带符合右移一位
0040101A  |.  50            push    eax
0040101B  |.  68 30704000   push    00407030      ;  ASCII "%d"
00401020  |.  E8 0B000000   call    00401030       ;printf函数
00401025  |.  83C4 08       add     esp, 8
00401028  |.  33C0          xor     eax, eax
0040102A  \.  C3            retn
0040102B      90            nop
Mov eax, idata              ;idata表示一个整数
Add eax, eax的符号位
Sar eax, 1

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 458
活跃值: (426)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
遗漏说明一下 :最终公式只对负数有效
正数是这个样子:Idata/(2^n) = YWn(idata)
2010-2-9 10:57
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
3
6个多小时 不顶说不过去
2010-2-9 10:57
0
雪    币: 458
活跃值: (426)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4
还不是脑袋转不过弯来  要是脑袋转的快   估计一会就能想明白了  呵呵
S大  帮看看有没有什么错误啊    万一错了  误导别人就不好了
2010-2-9 11:06
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
支持blueapplez
一堆公式看得有点晕
2010-2-9 13:01
0
雪    币: 65
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
看过类似的,没看过这么透彻的
2010-2-10 16:39
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
对于公式Idata/(2^n)=YWn(idata+2^n-1)
有一点需要说明,即intel使用的有符号除法的商是采取向零圆整的方式(如:(-5)/2=-2……-1,5/2=2……1),所以对于不能整除的数,移位的结果与商差1。这就是移位前加上(2^n-1)的原因。
由于不会使用论坛功能,把解释的内容粘贴到这里就走样了,所以放入附件。
对于这个公式理解后面加(2^n-1)的原因不是太难,难的是当初如何想到加(2^n-1)而不是别的数,向先驱们致敬!
向lz的专研精神致敬!
上传的附件:
2010-2-19 09:12
0
雪    币: 603
活跃值: (40)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
8
牛b啊,偶像啊
2010-2-19 21:13
0
雪    币: 458
活跃值: (426)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
9
to:fonilye
对于公式Idata/(2^n)=YWn(idata+2^n-1)
有一点需要说明,即intel使用的有符号除法的商是采取向零圆整的方式(如:(-5)/2=-2……-1,5/2=2……1),所以对于不能整除的数,移位的结果与商差1。这就是移位前加上(2^n-1)的原因。

这里是不是要分正数负数呢?
2010-2-20 09:13
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
对,正数的补码是其本身,除法和移位的结果是相同的,不需要修正(就是你第二帖中提出的那个正数公式)。
但对负数的补码,除法和直接移位的结果并不相同,如果用移位代替除法的话,可能需要修正(视移出部分是否为零而定)。我前一帖的解释只是对你提出的负数那个公式。
呵呵,是我的表述有问题
2010-2-20 10:29
0
雪    币: 0
活跃值: (984)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
我的理解就是整数 /2 ....余数 随他怎么变。 公式不变!
2010-4-20 11:02
0
雪    币: 154
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
2010-12-3 16:35
0
雪    币: 274
活跃值: (373)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
13
不错,对看反汇编代码很有帮助!
2010-12-3 21:11
0
雪    币: 45
活跃值: (51)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
<code>
Mov eax, idata              ;idata表示一个整数
Add eax, (eax的符号位)*(2^n - 1) ;这里n=4
Sar eax, n
</code>

你的这一段代码写得非常好. 但是似乎应该是反过来的:

<code>
Mov eax, idata              ;idata表示一个整数
Add eax, -(eax的符号位)*(2^n - 1) ;这里n=4
Sar eax, n
</code>
或者
<code>
Mov eax, idata              ;idata表示一个整数
SUB eax, (eax的符号位)*(2^n - 1) ;这里n=4
Sar eax, n
</code>

----------------------------------------------------------
即最后的结果是
1>如果 被除数 为 非负数 时候, 直接为
<code>
Sar eax, n    ; eax为被除数, 除数为 2^n
</code>

2>如果被除数 是负数时候, 为:
<code>
Mov eax, idata            
ADD eax, (2^n - 1)
Sar eax, n
</code>
2011-9-16 12:20
0
游客
登录 | 注册 方可回帖
返回