ESI用法不明确

时间:2016-04-28 12:28:36

标签: assembly x86

我目前正在调查程序集并反汇编一些代码(x86),并尝试从中重新创建C代码。我至少知道寄存器和编程的基础知识。但在以下情况下,我无法理解ESI的使用情况:

mov esi, [esp+10h]
lea esi, [esi+0]

我不确定esp+10h在这种情况下是什么,但我认为这不重要,因为它应该只是一些随机的32位值,对吧? / p>

据我所知,mov esi, [esp+10h]将从地址esp+10h复制数据(实际值)并将其存储在ESI中。所以esi现在应该是某种数据。但随后lea esi, [esi+0]出现并将esi+0(数据)解释为地址并将其写入esi

在我读过的stackoverflow的另一个帖子中,lea esi, [esi+0]实际上是nopWhat is the meaning of lea 0x0(%esi),%esi)。这是有道理的,因为它不应该修改地址。但是当esi是使用数据时,这令人困惑。所以我的C代码看起来像这样:

int esi = *(esp + 0x10); //move data from esp+10h to esi
int* esi = &esi;         //write the address of esi+0 to esi which is
                         //actually an int and not int*

所以我的问题是,如果寄存器级别的数据和地址之间存在任何区别,或者它是否只是被解释为它,因为它看起来是相同的(32位寄存器)。我的另一个问题是这个代码现在实际上做了什么以及ESI到底是什么? mov是否始终复制数据? lea是否总是复制一个无关紧要的地址?

你可能已经猜到了,我很困惑,也许我只是想得太远。请怜悯我:D

1 个答案:

答案 0 :(得分:3)

CPU没有像高级语言那样的数据类型。对于CPU,所有数据都只是位;将这些位解释为整数/位掩码/地址/浮点数只存在于程序员的脑海中。程序员有责任知道“这个32位值表示字符数组的地址,所以我只应该用它在那个上下文中有意义的事情”。但如果你做一些不太明智的事情,比如移动一个地址,机器就不会阻止你。

第一条指令取esp寄存器中的值(通常包含堆栈顶部的地址),添加10h,取32位来自该地址的值,并将其加载到esi寄存器中。此地址的值可能是局部变量或函数参数,并且正在加载到esi中以准备进一步的计算。

第二条指令获取esi寄存器中的值,加0,并将加载到esi。 (注意它不会从内存中获取任何内容,尽管指令的“间接”外观;这是lea指令的一个奇怪之处,它基本上计算一个地址,但不会取消引用它。你可以想到它有点像C的一元&。)正如你所说,这是一个无操作;是的,esi中有数据,但它自己被“替换”了。

请注意,机器中只有一个esi寄存器,因此将其声明为两个不同变量的代码会产生误导。将esi视为全局变量。

由于C确实有数据类型,要在C中获得类似的效果,您必须在整个地方进行类型转换。我会像这样表达代码:

int esi, esp;

esi = *(int *)(esp + 0x10);
esi = (int)&*(int *)esi; // does nothing

(您必须假设您可以将整数转换为指针并返回而不更改其值。)