我目前正在研究一些代码(X86)的组装和分解,在那里我尝试从它重新创建C代码。我至少知道寄存器和程序的基本知识。但在以下情况下,我无法理解ESI的用法:
mov esi, [esp+10h]
lea esi, [esi+0]我不确定在这种情况下esp+10h是什么,但我不认为这很重要,因为它应该是一些随机的32位值,对吗?
据我所知,mov esi, [esp+10h]将从esp+10h中复制数据(实际值),并将其存储在ESI中。所以esi现在应该是某种数据。但之后,lea esi, [esi+0]来将esi+0 (即数据)解释为一个附加项,并将其写入esi中。
在我看到的堆栈溢出的另一个线程中,lea esi, [esi+0]实际上是一个nop(What 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总是复制一个地址吗?不管怎样,这不重要吗?
你可能已经猜到了,我很困惑,也许我只是想的太远了。请宽恕我。
发布于 2016-04-28 16:30:34
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(您必须假设可以将整数转换为指针和返回,而不需要更改它们的值。)
https://stackoverflow.com/questions/36914729
复制相似问题