x86 反汇编/变量示例
你能说出以下访问器方法的原始 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++ 源代码大致是什么样的吗?
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** 相同的方式存储。