assembly 流行eip是法律的的指令?

1szpjjfi  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(97)

我正在做大学里的理论测试,有人问我这个问题:在一些指令之后,ESP增长了4,EIP增长了20,指令可能是什么?我把“流行”和“流行”都标上了。在nasm 32位汇编中是否可以执行pop eip指令?

pftdvrlh

pftdvrlh1#

**pop eip不是真实的的x86指令。**没有汇编程序会汇编它,AFAIK。

这是一个伪代码,用来解释ret的作用。参见操作部分in the manual。具体为正常“近”ret;far jmp/call/ret在“正常”32位代码中基本上不使用。
ret有自己的操作码,与pop的任何编码分离,x86也选择给予它一个单独的助记符。如果pop eip也被接受为0xc3操作码的另一个名称,这将是一个有效的设计。x86确实使mov助记符重载用于许多不同的操作码,包括mov到/来自control registersmov到/来自debug registers,以及整数寄存器和/或存储器或立即数之间的standard mov。(不过,mov的“标准”形式也有几种不同的操作码可供选择。)
但这会有点奇怪,因为push eip除了call +0之外并不存在,call +0的性能副作用就是跳变。
EIP不是8个通用整数寄存器之一,因此pop的正常编码无法编码ret。这就是为什么ret需要自己的操作码,以及为什么在asm源代码中有一个单独的助记符是有意义的。x86指令将寄存器编码为3位数,或者在x86-64上可选地编码为4位数。或者作为 * 隐式 * 源或目标,如muldiv的EDX:EAX,或pushf隐式读取EFLAGS:它只是由操作码暗示,没有任何特定 * 表示 * EFLAGS位。
ret不是魔术:它所做的只是弹出堆栈并将结果用作跳转目标。这取决于程序员,以确保ESP是指向一个地址,你想跳转到,通常是一个返回地址。
一些初学者无法理解这一点,认为ret会神奇地返回到最后一个call,所以他们没有把ret上的错误和他们的代码搞乱堆栈联系起来。
我肯定写过类似“ret是我们在x86上为pop eip使用的名称”的东西在SO回答和评论中很多次。
有趣的事实:在ARM 32位上,程序计数器 * 是16个整数寄存器之一,r15,所以你真的可以在一条指令中将pop {r4, pc}恢复保存的R4并将保存的lr(链接寄存器=返回地址)弹出到程序计数器中。因此,ARM实际上可以使用用于弹出通用整数寄存器的相同操作码来执行与pop eip等效的操作。
esp增长了4 eip增长了20
是的,我认为C3 ret or C2 00 00 ret 0是仅有的两个操作码可以做到这一点,并且都使用ret助记符。
如果EIP增长了15或更少,则add esp, 4pop eax的长编码可以解释它,例如。例如,具有多个冗余rep和/或fs前缀以及用于立即4imm32编码。
x86指令最多可以是15字节长;如果解码在15个字节之前没有到达指令的末尾,CPU会出现#UD异常,就像处理其他非法指令一样。因此,使用一条指令将EIP更改20个字节,只能使用跳转。而唯一 * 增加 * ESP的跳跃是ret;jmp / jcc不修改它,call推送返回地址。
iret几乎是可能的,但它弹出CS:IP,一个FLAGS值,和一个新的SS:SP:你不能让它弹出4个字节。(特别是在32位模式下。)
sysret不会修改ESP,并且只能由内核使用(环0)。sysexit从RCX和RIP = RDX设置RSP,但我很确定这不是他们想要的答案。:P

相关问题