pop eip不是真正的x86指令。 没有组装者可以组装它,AFAIK。
它是伪代码说明什么ret呢。请参阅手册中的“操作”部分。特别是正常的“附近” ret;far jmp / call / ret在“正常”的32位代码中基本上未使用。
ret有自己的操作码,与的任何编码分开pop,并且x86还选择为其提供单独的助记符。这将是一个有效的设计,因为pop eip它也可以被接受为0xc3操作码的另一个名称。mov对于许多不同的操作码,x86确实具有助记符重载,包括mov往返于控制寄存器,mov往返于调试寄存器以及整数寄存器和/或内存或立即数之间的标准mov。(不过,“标准”格式mov也有几种不同的操作码可供选择。)
但这有点奇怪,因为push eip不存在,因为call +0它具有跳转的性能副作用。
EIP不是8个通用整数寄存器之一,因此的常规编码pop无法对进行编码ret。这就是为什么ret需要自己的操作码以及为什么在asm源代码中使用单独的助记符的原因之一。x86指令将寄存器编码为3位数字,或者在x86-64上编码为4位。或作为隐式源或目的地,例如EDX mul或div,或pushf隐式读取EFLAGS:该操作码仅隐含它,而没有任何明确表示 EFLAGS的位。
ret这不是魔术:所做的只是弹出堆栈并将结果用作跳转目标。程序员应确保ESP指向您要跳转到的地址,通常是返回地址。
一些初学者未能理解这一点,并认为这ret会神奇地回到最后call,因此他们不会在错误ret和代码混乱之间建立联系。
我肯定在SO问题和答案中多次写过类似“ ret是x86上我们使用的名称pop eip ” 之类的东西。
有趣的事实:在ARM 32位上,程序计数器是 16个整数寄存器之一,r15因此,您真的可以在一条指令中将pop {r4, pc}已保存的R4还原并将已保存的lr(链接寄存器=返回地址)弹出到程序计数器中。因此,ARM实际上可以pop eip使用与弹出通用整数寄存器所用的相同操作码进行等效操作。
esp增长了4,eip增长了20
是的,我认为C3 ret或C2ret 0是唯一可以执行此操作的2个操作码,并且都使用ret助记符。
如果EIP增长了15或更少,则可能会对其进行长时间编码add esp, 4或对其pop eax进行解释,例如,使用多个冗余rep和/或fs前缀以及imm32即时编码4。
x86指令的最大长度为15个字节;如果解码在15个字节之前没有到达指令的末尾,则CPU会采取#UD异常处理,就像其他非法指令一样。因此,只有一条跳转才能通过一条指令将EIP更改20字节。而增加 ESP 的唯一途径是ret; jmp / jcc保持不变,call推送一个返回地址。
iret几乎有可能,但它会弹出CS:IP并带有FLAGS值:您无法让它仅弹出4个字节。(特别是在32位模式下。)
sysret不会修改ESP,并且只能由内核使用(0环)。 sysexit从RCX和RIP = RDX设置RSP,但是我很确定这不是他们想要的答案。:P
| 归档时间: |
|
| 查看次数: |
215 次 |
| 最近记录: |