我拿起《实践逆向工程》这本书,在第14页(x86汇编)上有以下示例:
mov eax, 0AAAAAAAh
mov ebx, 0BBBBBBBh
push eax
push ebx
pop esi
pop edi
现在,我将eax和ebx推入堆栈,但是我弹出堆栈的esi和edi。这是为什么?我以为我会推送并弹出相同的寄存器。
答案 0 :(得分:1)
您不推送寄存器,而是推送这些寄存器中保存的值。在这种情况下,值来自寄存器DoCmd.OpenForm "frmService", acNormal, , "WorkOrderID = " & Me!txtID, acFormEdit
和eax
。寄存器本身保留在原处(CPU内部的某个地方)。
您可以将这些值弹出到任何寄存器中,例如ebx
和esi
。它仅取决于代码中的位置以及需要这些值的寄存器。
有时您只想从堆栈中清除一些值。然后你可以做
edi
那不会影响任何其他寄存器。(当然,您也可以简单地更改堆栈指针,但这是另一个主题。)
答案 1 :(得分:1)
当您pop
堆栈时,寄存器操作数仅接收堆栈顶部的值。只要压入和弹出相同数量的字节,堆栈就会保持平衡,而不管字节在哪里。您不一定需要pop
回到原来的值push
所在的位置。
例如,此代码使用ecx
中当前存在的内容加载寄存器eax
,而不会导致堆栈未对齐:
push eax
pop ecx
您还可以通过手动调整堆栈指针来执行有效的“无操作数” pop
:
push eax
...
add esp, 4 ; Discard 32-bits on top of stack
; Stack is now balanced (assuming the intermediate instructions did not misalign the stack)
答案 2 :(得分:0)
推入—推入堆栈
push指令将其操作数放在内存中受硬件支持的堆栈的顶部。具体来说,首先将ESP递减4,然后将其操作数放入地址(%esp)的32位位置的内容中。由于x86堆栈向下增长,因此ESP(堆栈指针)通过推入递减-即,堆栈从高地址增长到低地址。
pop-从堆栈弹出
pop指令将4字节数据元素从硬件支持的堆栈的顶部移到指定的操作数(即寄存器或存储器位置)中。它首先将位于内存位置(%esp)的4个字节移至指定的寄存器或内存位置,然后将ESP递增4。
查找更多详细信息:push / pop explanation