我发现了这个汇编代码并在分析它时,我意识到我在这里看不到堆栈的清理或平衡。我认为可能像dword ptr [ebp-8]
那样访问堆栈等同于弹出内容。我是否正确,如果不是,那么为什么以下代码不显示pop
指令或add esp, whatever
??
_AddMe:
push ebp
mov ebp, esp
sub esp, 0ch
mov eax, dword ptr [ebp+0ch]
mov dword ptr [ebp-4], eax
mov eax, dword ptr [ebp+8]
mov dword ptr [ebp-8], eax
mov eax, dword ptr [ebp-8]
add eax, dword ptr [ebp-4]
mov dword ptr [ebp-0ch], eax
mov eax, dword ptr [ebp-0ch]
jmp AddMeEpilogue
AddMeEpilogue:
mov esp, ebp
pop ebp
ret
答案 0 :(得分:7)
您可以手动递增和递减堆栈指针,因此添加/减去esp基本上类似于推送和弹出操作。
示例强>
mov eax, 2134
push eax
mov ebx, [esp]
add esp, 04 <-- This is the actual pop operation.
mov ecx, [esp-4]
ret
您可以看到我在推送后没有弹出,但代码仍然执行正确并且类似于。
push eax
pop ebx
mov ecx, ebx
访问堆栈不会改变它的正确性。因此,如果你执行mov eax, dword ptr [ebp-0ch]
并不意味着堆栈将是正确的或不正确的,因为它只是从内存中取出一些恰好是堆栈的值。只有增加或减少ESP具有可被视为push
或pop
操作的含义。
答案 1 :(得分:4)
EBP
保存在堆栈中,然后设置为指向当前堆栈顶部(mov ebp,esp
)。
然后通过向下移动堆栈指针(sub esp,0ch
)在堆栈上分配局部变量的一些空间。然后使用EBP
减去一个偏移量来引用该区域中的数据(因为EBP
等于ESP
,然后再减去。< / p>
同时使用EBP
加上偏移量来访问函数参数。
在函数返回之前,它会将ESP
和EBP
(mov esp,ebp
设置ESP
恢复到它在push ebp
开头之后的值。功能)。