pop eip 指令合法吗?

2024-03-06

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


pop eip不是真正的 x86 指令。AFAIK,没有汇编器会组装它。

这是伪代码解释 what ret做。参见操作部分在手册中 https://www.felixcloutier.com/x86/ret。具体来说是正常的“附近”ret; far jmp/call/ret 在“正常”32 位代码中基本上未使用。

ret有自己的操作码,与任何编码分开pop,而x86也选择给它一个单独的助记符。这本来是一个有效的设计pop eip也被接受为0xc3操作码。 x86确实有mov许多不同操作码的助记符重载,包括mov至/自控制寄存器 https://www.felixcloutier.com/x86/mov-1, mov至/自调试寄存器 https://www.felixcloutier.com/x86/MOV-2.html,以及标准mov https://www.felixcloutier.com/x86/mov整数寄存器和/或内存或立即数之间。 (这种“标准”形式mov不过,也有几种不同的操作码可供选择。)

但这有点奇怪,因为push eip不存在,除了作为call +0它具有跳跃的性能副作用。

EIP不是8个通用整数寄存器之一,因此正常编码pop无法编码ret。这就是原因之一ret需要它自己的操作码,以及为什么它在 asm 源代码中有一个单独的助记符是有意义的。 x86 指令将寄存器编码为 3 位数字,或者在 x86-64 上选择 4 位数字。或者作为implicit源或目标,例如 EDX:EAXmul or div, or pushf隐式读取 EFLAGS:它只是由该操作码暗示,没有任何专门表示的位mean EFLAGS.


ret并不神奇:它所做的只是弹出堆栈并将结果用作跳转目标。由程序员来确保 ESP 指向您想要跳转到的地址,通常是返回地址。

有些初学者不明白这一点并认为ret会神奇地回到最后call,所以他们不会在故障之间建立联系ret他们的代码弄乱了堆栈。

我肯定写过类似的东西“ret是我们在 x86 上使用的名称pop eip”在多次回答和评论中。

有趣的事实:在 ARM 32 位上,程序计数器is16 个整数寄存器之一,r15,所以你真的可以pop {r4, pc}恢复已保存的 R4 并弹出已保存的lr(链接寄存器=返回地址)全部通过一条指令存入程序计数器。所以ARM实际上可以做相当于pop eip使用与弹出通用整数寄存器相同的操作码。


esp 增长了 4,eip 增长了 20

是的,我认为C3 ret或 C2 00 00ret 0 https://www.felixcloutier.com/x86/ret是唯一可以做到这一点的两个操作码,并且都使用ret助记符。

如果 EIP 增长 15 或更少,则长编码add esp, 4 or pop eax可以解释它,例如具有多个冗余rep and/or fs前缀和imm32立即编码4.

x86指令最多可以有15个字节长;如果解码在 15 个字节之前没有到达指令末尾,则 CPU 采取#UD例外,就像其他非法指令一样。因此,只有通过跳转才能用一条指令将 EIP 更改 20 个字节。唯一的跳跃增加 ESP is ret; jmp / jcc 保持不变,call推送返回地址。

iret几乎有可能,但它会弹出CS:IP、一个 FLAGS 值和一个新的SS:SP:你无法让它只弹出 4 个字节。 (特别是在 32 位模式下。)

sysret不修改 ESP,并且只能由内核(环 0)使用。sysexit https://www.felixcloutier.com/x86/sysexit从 RCX 和 RIP = RDX 设置 RSP,但我很确定这不是他们正在寻找的答案。 :P

16-bit retf可以在非常特殊的情况下工作:如果 EIP 位于 32 位地址空间的低 16 位,并且当前 CS 值已经在堆栈中。 16位跳转,包括retf,将EIP截断为IP。

我不是 100% 确定66h操作数大小覆盖前缀retf在 32 位模式下将只弹出 4 个字节而不是 6 个字节;中的伪代码https://www.felixcloutier.com/x86/ret https://www.felixcloutier.com/x86/ret says:

   // retf in protected mode, not vm86, RETURN-TO-SAME-PRIVILEGE-LEVEL:
            ELSE (* OperandSize = 16 *)
                    EIP := Pop();
                    EIP := EIP AND 0000FFFFH;
                    CS := Pop(); (* 16-bit pop *)

第一个 Pop() 被分配给一个 32 位寄存器;这会使其成为 32 位流行吗?但这部分伪代码即使在 16 位保护模式下也适用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pop eip 指令合法吗? 的相关文章

  • arm-thumb指令集的blx指令如何支持4MB范围

    读自https www keil com support man docs armasm armasm dom1361289866046 htm https www keil com support man docs armasm arma
  • 推送 64 位 intel osx

    我想将 64 位地址压入堆栈 如下所示 asm pushq 0x1122334455667788 但我得到编译错误 我只能按以下方式推送 asm pushq 0x11223344 有人可以帮助我理解我的错误吗 我是装配新手 所以如果我的问题
  • C/C++ 中的简单“Hello World”内联汇编语言程序

    我使用 devcpp 和 borland c 编译器 asm mov ax 4 I O Func mov bx 1 Output func mov cx name address of the string mov dx 6 length
  • 左/右旋转进位的实际用途

    循环左进位和循环右进位指令有哪些实际用途 在我的汇编课上 我们无法想出一个有用的好例子 如果要将位从一个操作数移出并移入另一个操作数 SHL EAX 1 move sign bit of EAX RCL EDX into LSB of ED
  • 装配中出现奇怪的字符?

    我写了以下代码 386 model small stack 100h data text db Paper 0 code start lea dx text mov ah 9h int 21h mov ah 4ch int 21h end
  • 为什么这个“std::atomic_thread_fence”起作用

    首先我想谈一下我对此的一些理解 如有错误请指正 a MFENCE在x86中可以保证全屏障 顺序一致性可防止 STORE STORE STORE LOAD LOAD STORE 和 LOAD LOAD 重新排序 这是根据维基百科 https
  • 在 REP MOVSW 之前 PUSH CS / POP DS 的目的是什么?

    为什么在下面的代码中我们压入代码段 PUSH CS 然后将其弹出到数据段 POP DS 我将这些行明确指定为 line1 和 line2 请告诉我 MOVSW 在这里是如何工作的 IF HIGHMEMORY PUSH DS MOV BX D
  • x86-64 上这个语句有什么问题?

    该函数的目的是获取堆栈的起始地址 unsigned long find start void asm movq rsp eax 当我编译它时 出现错误 Error suffix or operands invalid for movq mo
  • AVX512 掩码寄存器(k1...k7)的 GNU C 内联 asm 输入约束?

    AVX512 为其算术命令引入了 opmask 功能 一个简单的例子 上帝螺栓 org https godbolt org z P7xWD8 include
  • 什么时候汇编比C更快? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include
  • 取消的分支与常规分支有何不同?

    特别是对于 SPARC Assembly 取消的分支与常规分支有何不同 我一直认为 当我需要填充分支指令的 nop 延迟槽时 需要取消分支指令 但是 我认为我在这一部分上是不正确的 因为您可以在不取消分支的情况下填充 nop 如果不采用分支
  • 内联 asm 中不支持的指令“mov”将控制寄存器移动到 uint32_t

    我在 C 函数中使用汇编代码 但海湾合作委员会给出unsupported instruction mov 以下代码的错误 uint32 t faulting address asm volatile mov cr2 0 r faulting
  • 将两个 32 位整数向量相乘,生成 32 位结果元素向量

    将每个 32 位条目乘以 2 的最佳方法是什么 mm256i互相注册 mm256 mul epu32不是我正在寻找的 因为它产生 64 位输出 我想要每个 32 位输入元素都有一个 32 位结果 而且 我确信两个 32 位值的乘法不会溢出
  • 在 x86 Intel VT-X 非根模式下,是否可以在每个指令边界传递中断?

    除了不将中断传送到虚拟处理器的某些正常指定条件 cli if 0 等 之外 客户机中的所有指令实际上都是可中断的吗 也就是说 当传入的硬件中断先传递给 LAPIC 然后传递给处理器时 据说会发生一些内部魔法 将其转换为虚拟中断给来宾 使用虚
  • NASM 轮班操作员

    您将如何在寄存器上进行 NASM 中的位移位 我读了手册 它似乎只提到了这些操作员 gt gt lt lt 当我尝试使用它们时 NASM 抱怨移位运算符处理标量值 您能解释什么是标量值并举例说明如何使用 gt gt and lt lt 另外
  • Visual Studio 2017 上的简单装配程序

    386 model flat c stack 100h printf PROTO arg1 Ptr Byte data msg1 byte Hello World 0Ah 0 code main proc INVOKE printf ADD
  • 尝试使用 x86 程序集 GNU GAS 在数组索引处赋值时出现错误

    我在用x86GNU 与 GCC 的程序集 并尝试实现相当于以下内容的程序集c c int x 10 x 0 5 但是 当我尝试运行 使用命令 a out 我的汇编代码如下 第一次编译后gcc filename s 错误Segmentatio
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 两个基本的 ANTLR 问题

    我正在尝试使用 ANTLR 来获取简单的语法并生成汇编输出 我在 ANTLR 中选择的语言是 Python 许多教程看起来非常复杂或详细阐述与我无关的事情 我真的只需要一些非常简单的功能 所以我有两个问题 将值从一个规则 返回 到另一规则

随机推荐