A. 函数调用堆栈原理 push ebx push esi push edi是什么作用
[cpp] view plain
int goo(int a, int b)  
{  
    return a + b;  
}  
  
void foo()  
{  
    int a[] = {1, 2, 3};  
    int result = goo(a[1], a[2]);  
    printf("result: %d", result);  
}  
VS2010下编译
foo函数部分汇编:
[cpp] view plain
00EB3890  push        ebp    
00EB3891  mov         ebp,esp    
00EB3893  sub         esp,0E4h    
00EB3899  push        ebx    
00EB389A  push        esi    
00EB389B  push        edi    
00EB389C  lea         edi,[ebp-0E4h]    
00EB38A2  mov         ecx,39h    
00EB38A7  mov         eax,0CCCCCCCCh    
00EB38AC  rep stos    dword ptr es:[edi]    
00EB38AE  mov         eax,dword ptr [___security_cookie (0EB7000h)]    
00EB38B3  xor         eax,ebp    
00EB38B5  mov         dword ptr [ebp-4],eax    
    int a[] = {1, 2, 3};  
00EB38B8  mov         dword ptr [ebp-14h],1    
00EB38BF  mov         dword ptr [ebp-10h],2    
00EB38C6  mov         dword ptr [ebp-0Ch],3    
    int result = goo(a[1], a[2]);  
00EB38CD  mov         eax,dword ptr [ebp-0Ch]    
00EB38D0  push        eax    
00EB38D1  mov         ecx,dword ptr [ebp-10h]    
00EB38D4  push        ecx    
00EB38D5  call        goo (0EB11E5h)    
00EB38DA  add         esp,8    
goo函数完整汇编:
[cpp] view plain
00EB1580  push        ebp    
00EB1581  mov         ebp,esp    
00EB1583  sub         esp,0C0h    
00EB1589  push        ebx    
00EB158A  push        esi    
00EB158B  push        edi    
00EB158C  lea         edi,[ebp-0C0h]    
00EB1592  mov         ecx,30h    
00EB1597  mov         eax,0CCCCCCCCh    
00EB159C  rep stos    dword ptr es:[edi]    
    return a + b;  
00EB159E  mov         eax,dword ptr [a]    
00EB15A1  add         eax,dword ptr [b]    
}  
00EB15A4  pop         edi    
00EB15A5  pop         esi    
00EB15A6  pop         ebx    
00EB15A7  mov         esp,ebp    
00EB15A9  pop         ebp    
00EB15AA  ret    
foo函数push ebp, mov ebp, esp后
保存原ebp,设定新的ebp为当前esp位置
sub esp, 0E4h
给局部变量分配足够大的栈空间
保存原先的一些寄存器值,每次push,esp继续向下移
为局部变量a数组赋值
调用goo前Push两个参数,esp继续下移
call goo函数时,cpu自动push下一条指令地址,esp继续下移
在goo函数中,同样保存foo函数中的ebp值,设定新的ebp,esp等
在执行玩goo函数最后几句指令时,edi, esi, ebx恢复,esp同时也编程goo中ebp的位置,ebp恢复至foo函数原来的位置(pop ebp)
下一条指令也装入IP(ret指令),esp继续向上一步
foo函数中的add esp, 8将esp值继续往上(清除函数参数)
清除函数参数的工作也可通过ret X在goo函数返回时设定(这样的话不必在每次调用点上加上add esp, X指令缩短了编译出来的文件大小,但在子函数中清除将不能做到printf等的可变参数个数功能,因为子函数不知道具体有多少要参数进入了,只有调用处才知道)
B. 汇编指令 rep movs dword ptr es:[edi],dword ptr ds:[esi]
rep:重复执行指令复
rep movs dword ptr es:[edi],dword ptr ds:[esi]
意思就是制将ESI指向的地址的值以4字节方式拷贝到EDI指向的地址中,重复执行ECX次,每次执行后ESI+4,EDI+4,ECX-1,OD中在这段代码中下断后按F7单步步入就可以观察到这3个寄存器的变化
C. MOV [EDI+ESI],10H可以吗
不可以
1.操作数宽度不明
2.基址/变址寄存器不能同时出现在统一操作数寻址
D. 麻烦找出汇编语言中这个指令的错误:mov [esi],[edi]
MOV指令中,源操作数和目的操作数不能同时为存储器操作数。
E. edi,esi寄存器是什么寄存器有什么作用
EDI和ESI分别是16位寄存器DI和SI的32位扩展
它们是目的变址寄存器和源变址寄存器,用于串操作指令中。
同时,它们也可以作为通用寄存器使用。
F. 这段汇编代码是什么意思,赋值过来又赋值过去的,怎么找到esi edi的来源呢
这就是内存拷贝啊
esi指向原内存首地址,edi指向目标内存首地址,
esi和edi应该是运行是确定的,用gdb调试一下就知道是什么值了
G. MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]什么意思
DWORD PTR ES:[EDI],将来ES:[EDI]这个内存强制转换为源dword双字类型,PTR就是转换符,DWORD为双字类型,在汇编中有BYTE,WORD,DWORD几种变量类型,分别对应1,2,4个字节。
整个语句的意思就是把
DWORD PTR DS:[ESI】内存单元的值传送到DWORD PTR ES:[EDI]单元保存,因为内存单元一般是2个字节的,这里强制转换为4个字节!
MOV 就是传送子令
H. 汇编中eax,ecx,edx,ebx,esp,ebp,esi,edi,eip分别是什么有什么用
这些来是32位的CPU中32位的寄存器的名字自。
 
寄存器是CPU内部的用于运行中暂存数据的存储单元。
 
在PC用的16位CPU  8086、8088中,寄存器的名字分别是AX(累加器),BX(基址寄存器),CX(计数寄存器),DX(数据寄存器),SP(堆栈指针),BP(基址指针),SI(源变址寄存器),DI(目的变址寄存器),IP(指令指针),等等……
 
这些寄存器除了从名字可以看得出来的用途以外,一部分寄存器也可以作为通用的一般数据寄存使用。具体每个寄存器的功能要与各种具体的指令关联起来才能理解清楚。 
 
在386以上的32位CPU中,这些寄存器扩展成了32位的,名字就是在原来16位的名字前面加一个字母E,变成了EAX,EBX,…………
I. 汇编中mov esi,eax是什么意思!!!!
XXXX45A3 lea ecx, [esp+124h] 
XXXX45AA push ecx ; IX86ver0.dll 
XXXX45AB call ds:LoadLibraryA //加载DLL 
XXXX45B1 mov ebp, eax //句柄从eax返回 
XXXX45B3 test ebp, ebp 
XXXX45B5 jz loc_6FF046F1 //没成功退出 
XXXX45BB push offset aCheckrevision ; "CheckRevision" //函数名 
XXXX45C0 push ebp ; hMole //DLL句柄 
XXXX45C1 call ds:GetProcAddress //加载函数 
XXXX45C7 mov esi, eax //执行地址从eax返回 
XXXX45C9 test esi, esi 
XXXX45CB jnz short loc_6FF045DF //成功转移,到正常主力,否则有些出错处理等操作. 
XXXX45CD push offset aErrorFailedT_0 ; "<ERROR: Failed to execute Versioning DL"... 
XXXX45D2 call nullsub_1 //错误,提示,等等 
XXXX45D7 add esp, 4 
XXXX45DA jmp loc_6FF046EA 
//就存储空间来说,这里至少少了3~4个指令代码,因该是些有赋值操作,则带参数. 
XXXX46E6 call esi ; CheckRevision 
XXXX46E8 mov ebx, eax 
就这些代码来说CheckRevision是没有带参数.
J. 汇编语言 esi,edi寄存器问题
都属于通用寄存器,所以一般场景下都可以随便用。就是有些传送指令规定了esi是源,edi是目的