pop eip法律指示吗?

Avi*_*niv 1 x86 assembly 32-bit nasm

我正在上大学时进行的理论测试,并且被问到了这个问题:经过一番指导,esp增长了4,eip增长了20,指导可能是什么?我标记了“ pop eip”和“ ret”。在nasm 32位汇编中是否可以执行pop eip指令?

Pet*_*des 8

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 muldiv,或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