跳轉到內容

x86 反彙編/變數示例

來自華夏公益教科書

示例:識別 C++ 程式碼

[編輯 | 編輯原始碼]

你能說出以下訪問器方法的原始 C++ 原始碼大致是什麼樣的嗎?

 push ebp
 mov ebp, esp
 mov eax, [ecx + 8] ;THISCALL function, passes "this" pointer in ecx
 mov esp, ebp
 pop ebp
 ret

我們不知道類名,因此我們將使用一個通用的名稱 MyClass(或者您想稱呼它為任何名稱)。我們將列出一個簡單的類定義,它在偏移量 +8 處包含一個數據值。偏移量 +8 是唯一被訪問的資料值,因此我們不知道前 8 個位元組的資料是什麼樣的,但我們將假設(為了我們的目的)我們的類看起來像這樣

 class MyClass
 {
   int value1;
   int value2;
   int value3; //offset +8
   ...
 }

然後我們將建立我們的函式,我將它命名為“GetValue3()”。我們知道被訪問的資料值位於 [ecx+8] 處(我們在上面定義為“value3”)。此外,我們知道資料正在被讀入一個 4 位元組暫存器 (eax) 中,並且沒有被截斷。因此,我們可以假設 value3 是一個 4 位元組的資料值。我們可以使用 **this** 指標作為儲存在 ecx 中的指標值,並且我們可以從該指標(value3)獲取位於偏移量 +8 處的元素。

 MyClass::GetValue3()
 {
   return this->value3;
 }

**this** 指標在這裡不是必需的,但我仍然使用它來說明變數是如何作為 **this** 指標的偏移量被訪問的。

**注意**:請記住,我們不知道類中前 8 個位元組實際上是什麼樣的,我們只有一個訪問器方法,它只訪問偏移量 +8 處的單個數據值。該類也可以看起來像這樣

 class MyClass /*Alternate Definition*/
 {
    byte byte1;
    byte byte2;
    short short1;
    long value2;
    long value3;
  ...
 }

或者,任何其他 8 位元組的組合。

示例:識別 C++ 程式碼

[編輯 | 編輯原始碼]

你能說出以下設定器方法的原始 C++ 原始碼大致是什麼樣的嗎?

 push ebp
 mov ebp, esp
 cmp [ebp + 8], 0
 je error
 mov eax, [ebp + 8]
 mov [ecx + 0], eax
 mov eax, 1
 jmp end
 :error
 mov eax, 0
 :end
 mov esp, ebp
 pop ebp
 ret

這段程式碼看起來有點複雜,但不要驚慌!我們將慢慢地一步一步地進行。前兩行程式碼設定了堆疊幀。

 push ebp
 mov ebp, esp

接下來的兩行程式碼將 [ebp + 8](我們知道它是第一個引數)的值與零進行比較。如果 [ebp+8] 為零,函式跳轉到標籤“error”。我們看到標籤“error”將 eax 設定為 0,並返回。我們以前沒有見過它,但這看起來很像一個 **if** 語句。“如果引數為零,則返回零”。

另一方面,如果引數不為零,我們將值移入 eax,然後將值移入 [ecx + 0],我們知道它是 MyClass 中的第一個資料欄位。我們還從這段程式碼中看到,這個第一個資料欄位必須是 4 個位元組長(因為我們使用的是 eax)。在我們將 eax 移入 [ecx + 0] 之後,我們將 eax 設定為 1,並跳轉到函式的結尾。

如果我們使用與上面問題 1 中相同的 MyClass 定義,我們可以為我們的函式“SetValue1(int val)”獲得以下程式碼。

 int MyClass::SetValue1(int val)
 {
   if(val == 0) return 0;
   this->value1 = val;
   return 1;
 }

請注意,由於我們在失敗時返回 0,在成功時返回 1,因此該函式看起來像具有 **bool** 返回值。但是,返回值是 4 個位元組寬(使用的是 eax),但 **bool** 的大小是特定於實現的,因此我們不能確定。**bool** 通常被定義為具有 1 個位元組的大小,但它通常以與 **int** 相同的方式儲存。

華夏公益教科書