IRET/IRETD - 中断返回
来源:互联网 发布:python 模 编辑:程序博客网 时间:2024/06/05 16:11
转自:http://scc.qibebt.cas.cn/docs/optimization/VTune(TM)%20User's%20Guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/instruct32_hh/vc143.htm
http://szkn28szkn.iteye.com/blog/1362460
说明
将程序控制权从异常或中断处理程序返回异常、外部中断或软件生成的中断所中断的程序或过程。这些指令也用于执行从嵌套任务的返回。(使用 CALL 指令启动任务切换时,或是中断、异常导致任务切换到中断或异常程序时,都会创建嵌套任务)。请参阅“IA-32 英特尔(R) 体系结构软件开发人员手册”第 1 卷第 6 章中标题为“任务链接”的部分。
IRET 与 IRETD 是相同操作码的助记符。IRETD 助记符(中断返回双字)用于从使用 32 位操作数大小的中断返回;不过大多数汇编器对这两种操作数大小都互换使用 IRET 助记符。
在“实地址模式”中,IRET 指令执行到中断程序或过程的远返回。在执行此操作的过程中,处理器从堆栈将返回指令指针、返回代码段选择器以及 EFLAGS 映像分别弹入 EIP、CS 以及 EFLAGS 寄存器,然后恢复执行中断的程序或过程。
在“保护模式”中,IRET 指令的操作取决于以下因素:EFLAGS 寄存器中 NT(嵌套任务)与 VM 标志的设置,以及当前堆栈中存储的 EFLAGS 映像中的 VM 标志的设置。根据这些标志的设置,处理器执行以下类型的中断返回:
从虚 8086 模式返回。
返回到虚 8086 模式。
特权级别内返回。特权级别间返回。
从嵌套任务返回(任务切换)。
如果清除 NT 标志(EFLAGS 寄存器),则 IRET 指令执行从中断过程的远返回,而不执行任务切换。返回到的代码段的特权级别必须小于或等于中断处理例程的特权级别(如堆栈弹出的代码段选择器的 PRL 字段所示)。对于实地址模式中断返回,IRET 指令从堆栈将返回指令指针、返回代码段选择器以及 EFLAGS 映像分别弹入 EIP、CS 以及 EFLAGS 寄存器,然后恢复执行中断的程序或过程。如果返回到另一个特权级别,则在恢复程序执行之前,IRET 指令还从堆栈弹出堆栈指针与 SS。如果返回到虚 8086 模式,处理器还从堆栈弹出数据段寄存器。
如果设置 NT 标志,则 IRET 指令从嵌套任务(使用 CALL 指令、中断或异常调用的任务)执行任务切换(返回)到调用或中断的任务。执行 IRET 指令的任务的更新状态保存在它的 TSS 中。如果稍后重新进入该任务,则执行 IRET 指令后面的代码。
操作
IF PE 0THEN GOTO REAL-ADDRESS-MODE:;ELSE GOTO PROTECTED-MODE;FI;REAL-ADDRESS-MODE;IF OperandSize 32THENIF top 12 bytes of stack not within stack limits THEN #SS; FI;IF instruction pointer not within code segment limits THEN #GP(0); FI;EIP Pop();CS Pop(); (* 32-bit pop, high-order 16 bits discarded *)tempEFLAGS Pop();EFLAGS (tempEFLAGS AND 257FD5H) OR (EFLAGS AND 1A0000H);ELSE (* OperandSize 16 *)IF top 6 bytes of stack are not within stack limits THEN #SS; FI;IF instruction pointer not within code segment limits THEN #GP(0); FI;EIP Pop();EIP EIP AND 0000FFFFH;CS Pop(); (* 16-bit pop *)EFLAGS[15:0] Pop();FI;END;PROTECTED-MODE:IF VM 1 (* Virtual-8086 mode: PE=1, VM=1 *)THEN GOTO RETURN-FROM-VIRTUAL-8086-MODE; (* PE=1, VM=1 *)FI;IF NT 1THEN GOTO TASK-RETURN;( *PE=1, VM=0, NT=1 *)FI;IF OperandSize=32THENIF top 12 bytes of stack not within stack limitsTHEN #SS(0)FI;tempEIP Pop();tempCS Pop();tempEFLAGS Pop();ELSE (* OperandSize 16 *)IF top 6 bytes of stack are not within stack limitsTHEN #SS(0);FI;tempEIP Pop();tempCS Pop();tempEFLAGS Pop();tempEIP tempEIP AND FFFFH;tempEFLAGS tempEFLAGS AND FFFFH;FI;IF tempEFLAGS(VM) 1 AND CPL=0THEN GOTO RETURN-TO-VIRTUAL-8086-MODE; (* PE=1, VM=1 in EFLAGS image *)ELSE GOTO PROTECTED-MODE-RETURN;(* PE=1, VM=0 in EFLAGS image *)FI;RETURN-FROM-VIRTUAL-8086-MODE: (* Processor is in virtual-8086 mode when IRET is executed and stays in virtual-8086 mode *)IF IOPL=3 (* Virtual mode: PE=1, VM=1, IOPL=3 *)THEN IF OperandSize 32THENIF top 12 bytes of stack not within stack limits THEN #SS(0); FI;IF instruction pointer not within code segment limits THEN #GP(0); FI;EIP Pop();CS Pop(); (* 32-bit pop, high-order 16 bits discarded *)EFLAGS Pop();(*VM,IOPL,VIP,and VIF EFLAGS bits are not modified by pop *)ELSE (* OperandSize 16 *)IF top 6 bytes of stack are not within stack limits THEN #SS(0); FI;IF instruction pointer not within code segment limits THEN #GP(0); FI;EIP Pop();EIP EIP AND 0000FFFFH;CS Pop(); (* 16-bit pop *)EFLAGS[15:0] Pop(); (* IOPL in EFLAGS is not modified by pop *)FI;ELSE #GP(0); (* trap to virtual-8086 monitor: PE=1, VM=1, IOPL<3 *)FI;END;RETURN-TO-VIRTUAL-8086-MODE: (* Interrupted procedure was in virtual-8086 mode: PE=1, VM=1 in flags image *)IF top 24 bytes of stack are not within stack segment limitsTHEN #SS(0);FI;IF instruction pointer not within code segment limitsTHEN #GP(0);FI;CS tempCS;EIP tempEIP;EFLAGS tempEFLAGSTempESP Pop();TempSS Pop();ES Pop(); (* pop 2 words; throw away high-order word *)DS Pop(); (* pop 2 words; throw away high-order word *)FS Pop(); (* pop 2 words; throw away high-order word *)GS Pop(); (* pop 2 words; throw away high-order word *)SS:ESP TempSS:TempESP;(* Resume execution in Virtual-8086 mode *)END;TASK-RETURN: (* PE=1, VM=1, NT=1 *)Read segment selector in link field of current TSS;IF local/global bit is set to localOR index not within GDT limitsTHEN #GP(TSS selector); FI;Access TSS for task specified in link field of current TSS;IF TSS descriptor type is not TSS or if the TSS is marked not busyTHEN #GP(TSS selector); FI;IF TSS not present THEN #NP(TSS selector); FI;SWITCH-TASKS (without nesting) to TSS specified in link field of current TSS;Mark the task just abandoned as NOT BUSY;IF EIP is not within code segment limit THEN #GP(0);FI;END;PROTECTED-MODE-RETURN: (* PE=1, VM=0 in flags image *)IF return code segment selector is null THEN GP(0); FI;IF return code segment selector addrsses descriptor beyond descriptor table limit THEN GP(selector; FI;Read segment descriptor pointed to by the return code segment selectorIF return code segment descriptor is not a code segment THEN #GP(selector); FI;IF return code segment selector RPL < CPL THEN #GP(selector); FI;IF return code segment descriptor is conformingAND return code segment DPL > return code segment selector RPLTHEN #GP(selector); FI;IF return code segment descriptor is not present THEN #NP(selector); FI:IF return code segment selector RPL > CPL THEN GOTO RETURN-OUTER-PRIVILEGE-LEVEL;ELSE GOTO RETURN-TO-SAME-PRIVILEGE-LEVELFI;END;RETURN-TO-SAME-PRIVILEGE-LEVEL: (* PE=1, VM=0 in flags image, RPL=CPL *)IF EIP is not within code segment limits THEN #GP(0); FI;EIP tempEIP;CS tempCS; (* segment descriptor information also loaded *)EFLAGS (CF, PF, AF, ZF, SF, TF, DF, OF, NT) tempEFLAGS;IF OperandSize=32THENEFLAGS(RF, AC, ID) tempEFLAGS;FI;IF CPL IOPLTHENEFLAGS(IF) tempEFLAGS;FI;IF CPL 0THENEFLAGS(IOPL) tempEFLAGS;IF OperandSize=32THEN EFLAGS(VM, VIF, VIP) tempEFLAGS;FI;FI;END;RETURN-TO-OUTER-PRIVILGE-LEVEL:IF OperandSize=32THENIF top 8 bytes on stack are not within limits THEN #SS(0); FI;ELSE (* OperandSize=16 *)IF top 4 bytes on stack are not within limits THEN #SS(0); FI;FI;Read return segment selector;IF stack segment selector is null THEN #GP(0); FI;IF return stack segment selector index is not within its descriptor table limitsTHEN #GP(SSselector); FI;Read segment descriptor pointed to by return segment selector;IF stack segment selector RPL RPL of the return code segment selectorIF stack segment selector RPL RPL of the return code segment selectorOR the stack segment descriptor does not indicate a writable data segment;OR stack segment DPL RPL of the return code segment selectorTHEN #GP(SS selector); FI;IF stack segment is not present THEN #SS(SS selector); FI;IF tempEIP is not within code segment limit THEN #GP(0); FI;EIP tempEIP;CS tempCS;EFLAGS (CF, PF, AF, ZF, SF, TF, DF, OF, NT) tempEFLAGS;IF OperandSize=32THENEFLAGS(RF, AC, ID) tempEFLAGS;FI;IF CPL IOPLTHENEFLAGS(IF) tempEFLAGS;FI;IF CPL 0THENEFLAGS(IOPL) tempEFLAGS;IF OperandSize=32THEN EFLAGS(VM, VIF, VIP) tempEFLAGS;FI;FI;CPL RPL of the return code segment selector;FOR each of segment register (ES, FS, GS, and DS)DO;IF segment register points to data or non-conforming code segmentAND CPL > segment descriptor DPL (* stored in hidden part of segment register *)THEN (* segment register invalid *)SegmentSelector 0; (* null segment selector *)FI;OD;END:
影响的标志
根据处理器的操作模式,可能会修改 EFLAGS 寄存器中的所有标志与字段。如果执行从嵌套任务到前一项任务的返回,则根据前一项任务的 TSS 存储的 EFLAGS 映像修改 EFLAGS 寄存器。
保护模式异常
#GP(0) - 如果返回代码或堆栈段选择器为空。如果返回指令指针超出返回代码段限制。
#GP(选择器) - 如果段选择器索引超出描述符表格限制。如果返回代码段选择器 RPL 大于 CPL。如果相容代码段的 DPL 大于返回代码段选择器的 RPL。如果非相容代码段的 DPL 不等于代码段选择器的 RPL。如果堆栈段描述符的 DPL 不等于返回代码段选择器的 RPL。如果堆栈段不是可写的数据段。如果堆栈段选择器 RPL 不等于返回代码段选择器的 RPL。如果代码段的段描述符未指明它是代码段。如果 TSS 的段选择器将自己的局部/全局位设置为局部。如果 TSS 段描述符指出 TSS 忙或不可用。
#SS(0) - 如果堆栈的栈顶字节超出堆栈限制。
#NP(选择器) - 如果返回代码或堆栈段不存在。
#PF(错误代码) - 如果发生页错误。
#AC(0) - 如果在 CPL 是 3 且启用对齐检查的情况下发生未对齐的内存引用。
实地址模式异常
#GP - 如果返回指令指针超出返回代码段限制。
#SS - 如果堆栈的栈顶字节超出堆栈限制。
虚 8086 模式异常
#GP(0) - 如果返回指令指针超出返回代码段限制。如果 IOPL 不等于 3。
#PF(错误代码) - 如果发生页错误。
#SS(0) - 如果堆栈的栈顶字节超出堆栈限制。
#AC(0) - 如果在启用对齐检查的情况下进行未对齐的内存引用。
- IRET/IRETD - 中断返回
- iret
- 中断&中断返回
- ret & IRET
- iret指令
- 了解一下IRETD/ RET/ RETF
- 中断返回指令
- 关于IRET指令
- IRET指令详解
- ret/retf/iret
- iret指令详解
- Linux内核-中断-中断响应和返回
- 《NGNc,“中断”返回的结果》
- 从中断和异常返回
- 内核抢占与中断返回
- 汇编,ret retf iret指令
- ret,retf,iret的区别
- 上传文件中断: send返回10035
- 【Ibatis】(十三)、复杂类型属性(即自定义类型的属性)
- oracle 中 merge into 的使用
- GPRS模块在Linux平台上ppp拨号上网总结与心得
- getopt()函数的用法
- 【Ibatis】(十四)、cacheModel详解
- IRET/IRETD - 中断返回
- Uboot命令详解
- 用I2C通信实现点亮一盏小灯(包含应答)---c语言
- Swing用户界面设计
- 剖析C++标准库智能指针(std::auto_ptr) 以及智能指针的原理
- Hibernate与数据库触发器协同工作
- Flex画箭头
- StAX
- 事件不可思议的恋爱经历