portraiture教程-windows7版本
![memcpy](/uploads/image/0794.jpg)
2023年4月4日发(作者:rbcentry dll)
部分C库函数重写以及反汇编分析之memcpy()
为了打牢基本功,重写部分C库函数(参考C库与别⼈的代码,并给出了测试代码),并对部分进⾏反汇编分析(⽤VC⾃带反汇编和
OD)。在写程序过程中,会仔细验证很多以前模棱两可的知识点。
1.
/*从源src所指的内存地址的起始位置开始拷贝n个字节到⽬标dest所指的内存地址的起始位置中
和destin所指内存区域不能重叠,函数返回指向destin的指针。
2.与strcpy相⽐,memcpy并不是遇到'0'就结束,⽽是⼀定会拷贝完n个字节。
和destin都不⼀定是数组,任意的可读写的空间均可
*/
#include"stdafx.h"
#include
voidpmemcpy(void*dest,void*src,intn);
intmain(intargc,char*argv[])
{
//printf("HelloWorld!n");
char*a1="abc0def";
chara2[6];
printf("a1=%s,a2=%sn",a1,a2);
pmemcpy(a2,a1,5);
for(inti=0;i<6;i++)
{
printf("%c",a2[i]);
}
printf("n");
return0;
}
voidpmemcpy(void*dest,void*src,intn)
{
ASSERT((dest!=NULL)&&(src!=NULL));//assert宏的原型定义在
char*tmp_dest=(char*)dest;
char*tmp_src=(char*)src;
while(n--)
{
*tmp_dest=*tmp_src++;
tmp_dest++;
}
}
ps:对于a2[6]的初始化,a2[6]={0},将a2[0]初始化为0后,其余的各位也⾃动补0初始化,⽤printf("%s",a2)打印将不显⽰出。但是很奇
怪printf("%s",a2[0]);打印出来
反汇编分析:
debug⽅式编译,VC⾃带反汇编⼯具分析:
17:intmain(intargc,char*argv[])
15:{
00401020pushebp//保护启动函数的ebp值,将其⼊栈
00401021movebp,esp//ebp、esp同时指向栈底
00401023subesp,50h//esp-50h,留出main函数栈空间(分配给变量)
00401026pushebx
00401027pushesi
00401028pushedi//将ebx、esi、edi⼊栈
00401029leaedi,[ebp-50h]//通过ebp寻址
0040102Cmovecx,14h//为下⾯初始化刚刚留出的栈空间做准备,ecx作为循环填充的次数,50h/4=14h;
00401031moveax,0CCCCCCCCh//要填充的值
00401036repstosdwordptr[edi]//进⾏填充
char*a1="abc0def";
00401038movdwordptr[ebp-4],offsetstring"abc0def"(00422034)//00422034为“abc0def”字符串的索引地
址
18:chara2[6];
19:printf("a1=%s,a2=%sn",a1,a2);
0040103Fleaeax,[ebp-0Ch]//通过ebp-0ch索引变量a2,放⼊eax中
00401042pusheax//将变量eax(a2)⼊栈(函数main的栈)(参数⼊栈顺序为从右往左)
00401043movecx,dwordptr[ebp-4]
00401046pushecx//同上将参数a1⼊栈
00401047pushoffsetstring"a1=%s,a2=%sn"(00422024)//通过字符串索引将第⼀个参数⼊栈
0040104Ccallprintf(004011b0)//调⽤函数(跟进函数printf内部)
00401051addesp,0Ch//堆栈平衡原理,调⽤者⾃⼰清理堆栈
20:pmemcpy(a2,a1,5);//⼜是⼀个函数调⽤,不解释,参考上⾯
00401054push5
00401056movedx,dwordptr[ebp-4]
00401059pushedx
0040105Aleaeax,[ebp-0Ch]
0040105Dpusheax
0040105Ecall@ILT+0(pmemcpy)(00401005)
00401063addesp,0Ch
21:for(inti=0;i<6;i++)
00401066movdwordptr[ebp-10h],0//初始化变量i
0040106Djmpmain+58h(00401078)//跳转去00401078地址
0040106Fmovecx,dwordptr[ebp-10h]//将i存到ecx中
00401072addecx,1//i+1
00401075movdwordptr[ebp-10h],ecx//i+1后的值存回变量地址中
00401078cmpdwordptr[ebp-10h],6//将I与6进⾏⽐较
0040107Cjgemain+76h(00401096)//>=则跳
22:{
23:printf("%c",a2[i]);//同上,不解释.....
0040107Emovedx,dwordptr[ebp-10h]
00401081movsxeax,byteptr[ebp+edx-0Ch]
00401086pusheax
00401087pushoffsetstring"%c"(00422020)
0040108Ccallprintf(004011b0)
00401091addesp,8
24:}
00401094jmpmain+4Fh(0040106f)
25:printf("n");
00401096pushoffsetstring"n"(0042201c)
0040109Bcallprintf(004011b0)
004010A0addesp,4
26:return0;
004010A3xoreax,eax
27:}
voidpmemcpy(void*dest,void*src,intn)
30:{
004010F0pushebp
004010F1movebp,esp
004010F3subesp,48h
004010F6pushebx
004010F7pushesi
004010F8pushedi
004010F9leaedi,[ebp-48h]
004010FCmovecx,12h
004010FCmovecx,12h
00401101moveax,0CCCCCCCCh
00401106repstosdwordptr[edi]
31:ASSERT((dest!=NULL)&&(src!=NULL));
00401108cmpdwordptr[ebp+8],0//将第⼆个参数与0进⾏⽐较(仔细想想为什么是bep+8来索引的呢?)
0040110Cjepmemcpy+24h(00401114)//=0,则跳到00401114开始执⾏(其实就是打印⼀条出错信息,并结束程序)
0040110Ecmpdwordptr[ebp+0Ch],0//将第三个参数与0进⾏⽐较
00401112jnepmemcpy+48h(00401138)//!=则跳
00401114push0
00401116push0
00401118movsxeax,wordptr[`pmemcpy'::`2'::__LINE__Var(00424a30)]
0040111Faddeax,1
00401122pusheax
00401123pushoffsetstring"D:cxbfxe2xbaxafxcaxfdxd6xd8xd0xb4xc4xbfxc2xbcmemcpyme
00401128push2
0040112Acall_CrtDbgReport(00401380)
0040112Faddesp,14h
00401132cmpeax,1
00401135jnepmemcpy+48h(00401138)
00401137int3
00401138xorecx,ecx//应该是检验&&
0040113Atestecx,ecx
0040113Cjnepmemcpy+18h(00401108)
32:
33:char*tmp_dest=(char*)dest;
0040113Emovedx,dwordptr[ebp+8]
00401141movdwordptr[ebp-4],edx
34:char*tmp_src=(char*)src;
00401144moveax,dwordptr[ebp+0Ch]
00401147movdwordptr[ebp-8],eax
35:
36:while(n--)
0040114Amovecx,dwordptr[ebp+10h]//变量n存放到ecx
0040114Dmovedx,dwordptr[ebp+10h]//变量n存放到eax
00401150subedx,1//edx-1
00401153movdwordptr[ebp+10h],edx//将n-1存到变量n的地址中
00401156testecx,ecx//检测ecx是否为0(即n是否等于0了)
00401158jepmemcpy+88h(00401178)//n=0,则跳出循环
37:{
38:*tmp_dest=*tmp_src++;
0040115Amoveax,dwordptr[ebp-4]
0040115Dmovecx,dwordptr[ebp-8]
00401160movdl,byteptr[ecx]//将ecx中的值按字节存⼊dl寄存器中(指针取值运算)
00401162movbyteptr[eax],dl
00401164moveax,dwordptr[ebp-8]
00401167addeax,1
0040116Amovdwordptr[ebp-8],eax
39:tmp_dest++;
0040116Dmovecx,dwordptr[ebp-4]
00401170addecx,1
00401173movdwordptr[ebp-4],ecx
40:}
00401176jmppmemcpy+5Ah(0040114a)
41:}
00401178popedi/*以下都为堆栈平衡*/
00401179popesi
0040117Apopebx
0040117Baddesp,48h
0040117Ecmpebp,esp
00401180call__chkesp(00401230)
00401185movesp,ebp
00401187popebp
00401188ret
更多推荐
memcpy
发布评论