汇编返回指令ret iret retf区别

这是 8086 汇编中三个最容易混淆的返回指令。它们的区别在于从栈上弹出什么数据 以及如何恢复 CPU 执行状态

核心区别一览表

指令 操作码 弹出字节数 弹出的内容 典型配对 使用场景
RET C3 2 IP CALL NEAR 段内返回
RETF CB 4 IPCS CALL FAR 段间返回
IRET CF 6 IPCSFLAGS INT n 中断返回

详细分析

1. RET (Return from Near Call)

操作:

复制代码
IP ← [SP]
SP ← SP + 2

特点:

  • 只恢复指令指针 IP

  • 不改变 CS(仍在同一代码段)

  • 不恢复 FLAGS

对应调用: CALL NEAR(段内调用)

示例:

cpp 复制代码
    CALL NEAR func    ; 压入 IP
    ...
func:
    RET               ; 弹出 IP,返回调用处

2. RETF (Return from Far Call)

操作:

cpp 复制代码
IP ← [SP]      ; 先弹出 IP
SP ← SP + 2
CS ← [SP]      ; 再弹出 CS
SP ← SP + 2

特点:

  • 恢复 IPCS(实现段间跳转)

  • 不恢复 FLAGS

对应调用: CALL FAR(段间调用)或手动 PUSH CS + PUSH IP + RETF

你的监控程序中的例子(源码第 552 行):

cpp 复制代码
522 C287 A108FF      MOV AX,[USER_CS]    ; AX = 0000H
523 C28A 50          PUSH AX            ; 压入 CS
524 C28B A106FF      MOV AX,[USER_IP]   ; AX = 0400H
525 C28E 50          PUSH AX            ; 压入 IP
...(恢复其他寄存器)
552 C2B2 CB          RETF               ; 弹出 IP=0400, 弹出 CS=0000
                                        ; 跳转到 0000:0400(用户程序)

3. IRET (Return from Interrupt)

操作:

cpp 复制代码
IP ← [SP]      ; 弹出 IP
SP ← SP + 2
CS ← [SP]      ; 弹出 CS
SP ← SP + 2
FLAGS ← [SP]   ; 弹出 FLAGS
SP ← SP + 2

特点:

  • 恢复 IPCSFLAGS

  • 通常还会恢复中断允许标志(IF)(因为 INT 指令会自动清除 IF)

对应调用: INT n(软件中断)或硬件中断

栈帧对比图

执行 CALL NEAR 后的栈

cpp 复制代码
执行 CALL func 前              执行 CALL func 后
SP → [旧数据]                  SP → [返回 IP(2 字节)]
                               SP+2 → [旧数据]

执行 CALL FAR 后的栈

cpp 复制代码
执行 CALL FAR func 前          执行 CALL FAR func 后
SP → [旧数据]                  SP → [返回 IP(2 字节)]
                               SP+2 → [返回 CS(2 字节)]
                               SP+4 → [旧数据]

执行 INT n 后的栈

cpp 复制代码
执行 INT n 前                  执行 INT n 后
SP → [旧数据]                  SP → [返回 IP(2 字节)]
                               SP+2 → [返回 CS(2 字节)]
                               SP+4 → [FLAGS(2 字节)]
                               SP+6 → [旧数据]

常见错误

RET 代替 IRET:会导致 FLAGS 没有被弹出,栈不平衡,返回地址错误

IRET 代替 RET:会多弹出 2 字节当作 FLAGS,导致 IP 和 CS 错位

RETF 代替 IRET:FLAGS 没有被恢复,中断标志可能错误

正确原则:用什么指令调用,就用对应的指令返回

  • CALL NEARRET

  • CALL FARRETF

  • INT nIRET

相关推荐
怣疯knight1 天前
ida里打印python版本
汇编
是星辰吖~1 天前
X86反汇编_深度学习_栈反汇编分析
汇编
是星辰吖~1 天前
X86反汇编_深度学习_队列反汇编分析
汇编
say_fall1 天前
半导体存储器_从分类到Cache完全指南
汇编·微机原理·8086
是星辰吖~2 天前
x86反汇编_深度学习_单链表
汇编
是星辰吖~2 天前
x86反汇编_深度学习_链表OJ题反汇编
汇编
乾复道3 天前
k8s使用说明
汇编·程序人生
技术不好的崎鸣同学3 天前
x64汇编之堆栈工作原理理论篇(继上篇内容讲解)
汇编
是星辰吖~3 天前
X86汇编:复杂逻辑判断_针对性扫盲
汇编