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是目的