在呼叫物件的成員函式之前,會將物件的地址移動到 ECX。
在函式里面,ECX會被移到dword ptr [this],這是什么意思?
C 源代碼
#include <iostream>
class CAdd
{
public:
CAdd(int x, int y) : _x(x), _y(y) {}
int Do() { return _x _y; }
private:
int _x;
int _y;
};
int main()
{
CAdd ca(1, 2);
int n = ca.Do();
std::cout << n << std::endl;
}
拆卸
...
CAdd ca(1, 2);
00A87B4F push 2
00A87B51 push 1
00A87B53 lea ecx,[ca] ; the instance address
00A87B56 call CAdd::CAdd (0A6BA32h)
int Do() { return _x _y; }
00A7FFB0 push ebp
00A7FFB1 mov ebp,esp
00A7FFB3 sub esp,0CCh
00A7FFB9 push ebx
00A7FFBA push esi
00A7FFBB push edi
00A7FFBC push ecx
00A7FFBD lea edi,[ebp-0Ch]
00A7FFC0 mov ecx,3
00A7FFC5 mov eax,0CCCCCCCCh
00A7FFCA rep stos dword ptr es:[edi]
00A7FFCC pop ecx
00A7FFCD mov dword ptr [this],ecx ; ========= QUESTION HERE!!! =========
00A7FFD0 mov ecx,offset _CC7F790E_main@cpp (0BC51F2h)
00A7FFD5 call @__CheckForDebuggerJustMyCode@4 (0A6AC36h)
00A7FFDA mov eax,dword ptr [this] ; ========= AND HERE!!! =========
00A7FFDD mov eax,dword ptr [eax]
00A7FFDF mov ecx,dword ptr [this]
00A7FFE2 add eax,dword ptr [ecx 4]
00A7FFE5 pop edi
00A7FFE6 pop esi
00A7FFE7 pop ebx
00A7FFE8 add esp,0CCh
00A7FFEE cmp ebp,esp
00A7FFF0 call __RTC_CheckEsp (0A69561h)
00A7FFF5 mov esp,ebp
00A7FFF7 pop ebp
00A7FFF8 ret
uj5u.com熱心網友回復:
MSVC 的 asm 輸出本身(https://godbolt.org/z/h44rW3Mxh)在這樣的除錯版本中使用_this$[ebp]with _this$ = -4,這會浪費指令存盤/重新加載傳入暫存器 args。
_this$ = -4
int CAdd::Do(void) PROC ; CAdd::Do, COMDAT
push ebp
mov ebp, esp
push ecx ; dummy push instead of sub to reserve 4 bytes
mov DWORD PTR _this$[ebp], ecx
mov eax, DWORD PTR _this$[ebp]
...
這只是將暫存器 arg 溢位到具有該名稱的堆疊上的本地。(我在 Godbolt 上使用的 MSVC 版本的默認選項,x86 MSVC 19.29.30136,不包括__CheckForDebuggerJustMyCode@4或運行時檢查堆疊中毒 ( rep stos) Do(),但 的用法this仍然存在。)
有趣的是,push ecx它使用(作為微優化)而不是sub esp, 4保留已經存盤的 ECX 的堆疊空間,使mov存盤變得多余。
(AFAIK,實際上沒有編譯器確實使用push初始化并為本地人騰出空間,但這將是對這樣的情況的優化:什么 C/C 編譯器可以使用 push pop 指令來創建區域變數,而不是僅僅增加一次 esp?。它只是使用push它對 ESP 的影響,而不關心它存盤的內容,即使您啟用了優化。在它確實仍然需要溢位它的函式中,而不是將它保存在記憶體中。)
您的反匯編程式顯然將框架指標 ( EBP )折疊成它定義為this符號/宏的內容,如果您不環顧其他行以了解它如何定義該文本宏或其他任何內容,則會更加混亂。
你用的是什么反編譯器?Visual Studio 除錯器中內置的那個?
我想它以這種方式使用 C 本地 var 名稱是有道理的,盡管對于熟悉 asm 的人來說它看起來非常奇怪。(因為只有靜態存盤才能使用[symbol]不涉及任何暫存器的模式尋址。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/357367.html
上一篇:匯編跳轉后是否清除比較標志?
