-
-
[原创]字符串函数的汇编实现
-
发表于:
2010-2-13 11:25
10109
-
在项目开发过程中,对字符串的处理是经常遇到的问题,稍有不慎,就会留下一些不易察觉的瑕疵;熟练使用字符串函数,理解其实现过程,对编程会大有裨益;
在开始之前,请思考一下,是否真的明白了这样几个函数的用法。
1. sizeof,这不是函数,而是一个运算符,在编译时就已经计算好了参数所占用的内存空间,并分配;
2. strlen,函数,运行时计算参数中的元素个数,不包括'\0'结束符
对应的版本有两个:strlenA窄字符版本,strlenW宽字符版本
3. strcpynA, strcpyA的区别,strcpynA中的 unsigned long len长度表示的是内存长度还是元素个数,从什么地方开始计算
4. 快速求出一个字符串的最后元素,可以用前面方法的组合,也可以自己实现一个函数strendA
5.在前面几个函数的基础上,就可以自己实现strcatA等一些扩展函数
6.如果上面的都十分清楚,那可以分析下内部实现,增强功力;汇编、数据结构、这些都是作为一个程序员所应具备的功底。
一点说明:WINDOWS 提供的大多库函数都是fastcall调用约定,顾名思义,就是为了提高传输参数的效率而使用的一个调用约定;我们知道,传递参数,要么用堆栈,要么用寄存器,而fastcall调用约定就是二者的结合;前两个参数用ecx,edx分别传递,之后的参数用堆栈从右向左依次传递。
现在,感兴趣的可以看下面的代码。代码是我经过严格测试的,注释也是为了方便大家阅读加上去的。
//
// ANSI字符串求元素个数
//
__declspec(naked) unsigned long __fastcall strlenA(const char *s)
{
__asm
{
mov edx, edi //保存edi的值,到后面用 mov edi,edx恢复
mov edi, ecx //将参数ecx传递给edi,也就是说edi指向的内存空间存储字符串s
or ecx, -1 //初始化ecx 为 0FFFFFFFFh
xor eax, eax //初始化 eax =0
repne scasb //scan byte,字符串搜索,在edi指向的内存空间中搜索与al相等的值,也就是结束符0
dec eax // eax-1,这里,eax = -1,和repne scasb执行之前的ecx的值一样
dec eax // eax-1,相当于减去了'\0'的长度
sub eax, ecx //执行repne scasb的过程中,每循环一次,ecx--,那么sub eax,ecx 就是元素的个数了
//这里比较巧妙,运算都是在负数范围内,元素的个数也就是eax与ecx相对与0的距离之差
mov edi, edx
retn //返回值在eax默认返回
}
}
//
// WIDE CHAR 字符串求元素个数
//
__declspec(naked) unsigned long __fastcall strlenW(const wchar_t *s)
{
__asm
{
mov edx, edi
mov edi, ecx
or ecx, -1
xor eax, eax
repne scasw //scan word,结构和思想与strlenA函数一样,只是这里,我们是每次比较word长度的单位(2字节)
//每循环一次,ecx--,edi +=2
dec eax
dec eax
sub eax, ecx
mov edi, edx
retn
}
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)