首页
社区
课程
招聘
[原创]【老刘谈算法006】直接从内存中找答案——字符串转双字函数分析(3)
发表于: 2019-3-6 14:12 5213

[原创]【老刘谈算法006】直接从内存中找答案——字符串转双字函数分析(3)

2019-3-6 14:12
5213

以前听罗老师说不建议用masm32自带的宏、lib,可能有各种奇葩错误,我还不大相信,直到我看到了这个函数。
这个函数看着工工整整,算法的可行性也在上一篇分析过了,但其实完全无法工作。
为什么呢?请看第24、26行,
为了使ecx储存结果,函数在调用winAPI之前将ecx清零,
但这么做其实是徒劳的,WinAPI执行后,ebx、edi、esi和ebp的值总是不会被改变的,但 ecx 和 edx 的值有极大几率被改变。(同时这也是win对api调用的callback的要求)
这就导致ecx有了一个未知的初始值,导致累加发生在一个未知值的基础上,最终得到了没有任何意义的返回值。

这个函数支持有符号数,好评。

补码是当今广泛使用的有符号数编码规则,
负数表示为其绝对值表示的正数按位取反再+1(或-1后按位取反),
补码的优点是用无符号数规则进行有符号数加减计算,结果仍满足补码规则,且符合数学运算规定。

这个函数对有符号数的处理可谓颇为巧妙,
若字符串的第一个符号不是“-”,函数会将其按照正数处理,令edx为0,
在执行到49行时,ecx中就储存了正确的结果,而由于edx为0,不会改变ecx的值,就相当于执行了eax=ecx+0,eax中储存正确的结果。
由于0 xor any=any,下一行的xor不会改变eax的值。
若字符串的第一个符号是“-”,edx将会=0xFFFFFFFF,
这样,49行会使eax-=1,
由于edx的所有二进制位均为1,所以any xor edx=not any,50行实际上将eax进行了按位取反操作,
这样,eax正好满足补码规则,被顺利的转换为负数。

39~45行《字符串转双字函数分析(1)》已经做了详细讨论,不再赘述。

masm32的lib帮助文件中居然说这个函数没有返回值(黑人问号脸),其实是有的(要不咱执行这个函数图个什么),在eax中。

从文件名就能看出,这个asm里面有十进制(dec)的表(tbl)。有什么用呢?请看下文。

由于返回值的最大值为0xFFFFFFFF,即无符号数4294967295,所以string的长度应<=10,
由于是使用位运算来一次判断4个byte,所以只需要三次就能达到要求,为了提高效率,此代码采用了重复代码的方式,避免了多余的跳转。
一次判断4个byte的分析可见《老刘谈算法001》,不再赘述。

在执行到64行时,ecx中得到的是字符串的最后一个字符(个位)的ascii码,下面的一条指令却难以理解,add eax, [ecx*4+decade-192]是什么意思呢?
观察dectbl.asm中decade的定义,发现其共有10行,从个位向高位递增,每列都有10个dword数据,其最高位从0~9递增,超过dword无符号范围的数则被定义成0。
ecx中的值经过*4后,得到的是4x30H+4x(ascii对应的数),而4x30H正好=192,即那行指令中的-192是为了将ascii码转为byte,
这样,由于dword为4字节,[ecx*4+decade-192]就能正确将ascii码对应到表中第一行的数据。
同理,70行的decade+40将起始地址指向了表中的第二行,正好ecx中储存的是string中的十位对应的ascii码。
该算法虽浪费了一些空间,但免去了10的幂的计算,换得了实在的效率。

由于该代码在第17行需要用到[ebp+12],即调用函数前的[esp],
所以需要这样调用才能避免函数执行后[esp]被改变。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-3-7 11:36 被老刘NoOne编辑 ,原因: 修正格式,添加“调用方法"
收藏
免费 3
支持
分享
最新回复 (3)
雪    币: 3797
活跃值: (769)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
汇编底子差, 第一张图24 26行没明白意思
2019-3-8 14:00
0
雪    币: 2359
活跃值: (528)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
gaoan 汇编底子差, 第一张图24 26行没明白意思
24行就是下面文字叙述中所说的“清空ecx“
本意是ecx=ecx xor ecx,
由于异或时二进制位相同得0,不同得1,且ecx必定和ecx相同,
所以起到了清零的效果。
26行是调用了一个计算字符串长度的api
2019-3-8 16:05
0
雪    币: 3797
活跃值: (769)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
老刘NoOne 24行就是下面文字叙述中所说的“清空ecx“ 本意是ecx=ecx xor ecx, 由于异或时二进制位相同得0,不同得1,且ecx必定和ecx相同, 所以起到了清零的效果。 26行是调用了一 ...
谢谢老哥 我昨天是手机看的 不知道怎么回事 好像排版不对 今天看就对了 感谢回复 
2019-3-9 23:48
0
游客
登录 | 注册 方可回帖
返回
//