我正在读一本关于集会的书,我正试图学习一点这种语言。我得到了一些代码来了解他一直在做什么,但我遇到了麻烦。
有人可以解释下面代码的原因吗?
push ebp //put in top the stack, right?
mov ebp, esp //mov the value esp to ebp
push ecx // ok...
mov eax, [ebp+8] //What's ebp+8?
add eax, [ebp+0Ch] //What's ebp+0Ch?
add eax, [ebp+10h] //What's ebp+10h
mov [ebp-4], eax //What's ebp-4
mov eax, [ebp-4]
mov esp, ebp
pop ebp
retn
总结:是什么让这段代码? 我对此一无所知。
答案 0 :(得分:3)
我将用它的作用评论每一行:
push ebp //Saves EBP
mov ebp, esp //Establishes a pointer
push ecx //Creates local storage
mov eax, [ebp+8] //This retrieves the 1st parameter
add eax, [ebp+0Ch] //This retrieves the 2nd parameter
add eax, [ebp+10h] //This retrieves the 3rd parameter
mov [ebp-4], eax //This holds the original ECX, now overwritten by the sum of all 3 parameters
mov eax, [ebp-4] //This sum is the final result in EAX
mov esp, ebp //Forgets about the local storage
pop ebp //Restores EBP
retn //Returns
使用push ecx
创建本地存储可以缩短程序
另一种方法是sub esp,4
因此,这段代码的最终目标是计算3个数字的总和。
答案 1 :(得分:1)
在解释代码之前,必须定义PUSH
OpCode的功能:
它递减堆栈指针,然后将源操作数存储在堆栈顶部。
因此,首先,以下两行创建标准的 Stack Frame 。他们将EBP
分配给堆栈指针(ESP
)的当前位置,这对于通过相对于EBP
引用它们来访问堆栈上的局部变量非常有用(所谓的 Base-Pointer )。
push ebp //put in top the stack, right?
mov ebp, esp //mov the value esp to ebp
现在EBP
指向当前的堆栈位置。
以下行将ECX
推送到堆栈(ESP
) - 将ESP
减少4. EBP
保持不变。
push ecx // ok...
因为EBP
在调用此函数减去4(参见上文)时仍指向堆栈位置,因此以下行
mov eax, [ebp+8] //What's ebp+8?
将第一个参数EBP+8
移至EAX
。
记住:
CALL
推送的返回地址)PUSH EBP
之后:ESP = x-4(=返回地址为ESP + 4)EBP
设置为:ESP = x-4(EBP = ESP = x-4(现在指向EBP的旧值))EBP+4
,第一个参数位于EBP+8
(32位= 4字节)。 依此类推:
add eax, [ebp+0Ch] //What's ebp+0Ch?
[EBP+0Ch]
是第二个参数...
add eax, [ebp+10h] //What's ebp+10h
[EBP+10h]
是第三个参数。
因此,以下行将EAX
复制到堆栈上的32位值。哪个ECX
,PUSH
到上面的堆栈。
mov [ebp-4], eax //What's ebp-4
使用以下行复制ECX
局部变量是没用的......
mov eax, [ebp-4]
现在通过将EBP
复制回ESP
来恢复堆叠帧。
mov esp, ebp
pop ebp
以下行仅向调用者执行 32位接近返回:
retn
我认为这很好地解释了这个子程序的功能。