今天阅读巨龙公司系统集成开发部 杨屹 的《uCOS51移植心得》时看到一句话:RETI指令复位中断系统,RET则没有。实践表明,对于MCS-51,用子程序调用入栈,用中断返回指令RETI出栈是没有问题的,反之中断入栈RET出栈则不行。总之,对于入栈,子程序调用与中断调用效果是一样的,可以混用。在没有中断发生的情况下复位中断系统也不会影响系统正常运行。具体原因,文中并没有点明。由此引发ret和reti指令到底什么区别呢?

查看帮助手册,关于reti的说明如下:

RETI
The RETI instruction is used to end an interrupt service routine. This instruction pops the high-order and low-order bytes of the PC (and decrements the stack pointer by 2) and restores the interrput logic to accept additional interrupts. No other registers are affected by this instruction.The RETI instruction does not restore the PSW to its value before the interrupt. The interrupt service routine must save and restore the PSW.Execution returns to the instruction immediately after the point at which the interrupt was detected. If another interrupt was pending when the RETI instruction is executed, one instruction at the return address is executed before the pending interrupt is processed.See Also: RET

关于ret的说明如下:

RET
The RET instruction pops the high-order and low-order bytes of the PC from the stack (and decrements the stack pointer by 2). Program execution resumes from the resulting address which is typically the instruction following an ACALL or LCALL instruction. No flags are affected by this instruction.See Also: ACALL, LCALL

过一眼便知,reti做的事肯定比ret多(傻啊,只要不眼瞎都能看出来 ^_^)

先来说说两个指令做的相同的部分:从堆栈中依次弹出2个字节到PC的高位字节和低位字节, 都没有将PSW出栈的过程,所以系统在响应中断前,只将程序指针PC保存起来 PSW却没有保护起来。—— 这点与8086有些不同,8086中ret指令要做的就是从堆栈中弹出一个字到指令指针寄存器 IP 中,而iret从堆栈中弹出(恢复)IP、CS 和 FLAGS 的原始内容,于是转到主程序接着执行。

因为没有保存PSW,所以 中断服务程序中首先应该把PSW保存在栈中或者寄存器中,在中断服务程序结束前,再将PSW的值恢复,使正常程序流程不被破坏。

两者的区别呢? 从上面可以看到,reti还要恢复什么interrupt logic,那么interrupt logic是什么呢?

百度之 ... ...

以下内容来自网络:

------------------------------------------------------------------------------------------------------------------------------------------

资料指出“根据8051的结构特点,其中断系统中含有两个不可寻址的“优先级生效”触发器。一个用于指出CPU是否正在执行高优先级的中断服务程序,这个触发器为1时,系统将屏蔽所有的中断请求;另一个则指出CPU是否正在执行低优先级中断服务程序,该触发器为1时,将阻止除高优先级以外的一切中断请求。由此可见,若要响应同级甚至是低级中断请求,必须使得该“优先级生效”触发器清零。但该触发器又是不可寻址的,所以无法用软件直接清零。

通常情况下,在普通的汇编子程序中用RET做返回,在中断服务子程序中用RETI起中断返回作用。两条指令都能从堆栈中弹出断点地址并装入PC中,使 CPU回到原来主程序的断点处继续运行。然而,RET和RETI有本质的区别:当某一中断源响应后,单片机中的标志寄存器flag H和flag L其中的一个将会自动置位,用于阻止比它低级或同级的中断触发。RETI可以清除“优先级激活触发器”(即flag寄存器),以保证后续中断源的及时响应。所以,当把RETI替换为RET后,该程序在第一次运行时可能不会出错,但在第二次运行时就会出错了!
------------------------------------------------------------------------------------------------------------------------------------------

意思就是说:51内核中有两个不可见的中断优先级状态寄存器,用于指示发生了中断。 因为有二级中断,所以用了两个。 当用reti返回时,除了执行ret相同的功能外,还会清相应的的状态的寄存器。如果在中断中用ret返回,由于没清相应的状态寄存器,则此后不能进同级别中断。

reti除了相关的栈操作以外,还有可能要清除一些可以硬件清除的中断请求标志位,同时复位中断控制系统,以使后继发生的中断可以被有效响应。可以设想,如果允许在中断服务子程序中使用RET返回会导致CPU对该返回操作的二义理解:究竟是中断服务子程序的返回呢,还是在中断中调用了某一个子函数的返回呢?毕竟我们不能不允许在中断服务子程序中调用其他子函数吧?

所以,为了消除这种二义性,在中断服务子程序中使用reti返回~!

总结以下:

① 在非中断过程调用的子程序用ret和reti返回是可以相互替代的 -- 因为在没有中断发生的情况下复位中断系统也不会影响系统正常运行。

② 如果在中断过程中调用的子程序也用reti返回,那么中断状态寄存器触发器会被提前清除,那么实际上中断过程仍在继续,而这时又有其他中断源来临(即便中断源优先级和此时中断程序的优先级相比低或者相同),系统也会响应新的中断源。
 
③ 如果在中断服务程序中的返回用的是ret来代替,虽然响应完一次中断后能正常返回,但是中断状态寄存器触发器没有被清除。那么如果有比其优先级低或者优先级相同的中断请求,MCS-51将不会响应请求, 但是只要程序中任何地方再执行一次RETI(比如子程序返回),中断仍会继续响应

④ 在中断服务程序总PUSH和POP指令必须成对使用,否则不能正确返回断点(其实非中断过程调用也一样)

简而言之 
 中断函数返回用reti,
    普通函数返回及中断函数中调用的普通函数返回用ret。

参考链接:

http://www.cnblogs.com/alimy/archive/2013/02/22/2921765.html

http://bbs.huazhoucn.com/Temp/Temp4180_1.html

http://wenku.baidu.com/view/a4416136b90d6c85ec3ac652.html

51中ret和reti的区别相关推荐

  1. 51单片机 ret和reti

    // 以前还真不知道这种隐藏的寄存器,现在学习了 // 以下转载 原来在8051构架中--中断系统中含有两个不可寻址的"优先级生效"触发器.一个用于指出CPU是否正在执行高优先级的 ...

  2. java中separator_java - File.separator和路径中的斜杠之间的区别

    java - File.separator和路径中的斜杠之间的区别 在Java Path-String中使用/和普通的File.separator有什么区别? 与双反斜杠相比,/平台独立似乎不是原因, ...

  3. JavaScript 中 Property 和 Attribute 的区别

    转自:http://www.cnblogs.com/elcarim5efil/p/4698980.html property 和 attribute非常容易混淆,两个单词的中文翻译也都非常相近(pro ...

  4. c语言程序中函数调用本身叫什么,在C语言中函数调用方式有什么区别

    在使用VC进行函数定义时,通常会指定该函数调用方式,那么在C语言中函数调用方式有什么区别呢?下面小编找到了一下教程,分享给大家,希望可以帮助到大家. 通常在使用VC进行函数定义时会指定该函数调用方式, ...

  5. ntoskrnl.exe中Zw*与Nt*的区别

    某些Zw*和Nt*函数既在ntdll.dll中导出又在ntoskrnl.exe中导出,他们有什么区别呢? 我们分三部分比较: step 1: ntdll.dll中的Zw*和Nt*有什么区别? step ...

  6. Linux中线程和进程的区别

    Linux中线程和进程的区别 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,它是系统进行资源分配和调度的一个独立单位.例如,用户运行自己的程序,系统就创建一个进程,并为它分配资源,包括 ...

  7. python中break和continue的区别

    python中break和continue的区别 break 结束for 或者while 循环  后面还没循环到的 不再循环 continue 当满足某种条件时结束当前值的循环 后面没有循环的继续循环 ...

  8. PHP中self和static的区别,php中self与static的区别

    原文链接,猛击这里. php中self与static的区别 通过一些示例,我们可以很容易看出self和static的区别.假定我们有class Car – 它有两个方法,model和getModel. ...

  9. php 抽象类 接口 区别,PHP中抽象类、接口的区别与选择分析

    本文实例分析了PHP中抽象类.接口的区别与选择.分享给大家供大家参考,具体如下: 区别: 1.对接口的使用是通过关键字implements.对抽象类的使用是通过关键字extends.当然接口也可以通过 ...

最新文章

  1. python俄罗斯方块算法详解_用 Python 写一个俄罗斯方块游戏 (
  2. Bzoj4817:[SDOI2017]树点涂色
  3. Day-10: 错误、调试和测试
  4. vs中实现声音录制并保存到指定文件_别人直播怎么录制视频?这三种方法你可以不知道...
  5. ubuntu 中文设置
  6. (转载)二进制与三进制的妙用
  7. 23种设计模式(十三)接口隔离之门面模式
  8. html转义字符 am,html转义字符如何通过代码识别方法
  9. 目标检测NMS非极大值抑制及改进
  10. contiki CC2530 CC2430例子描述
  11. 手机问卷调查报告 html,关于手机的问卷调查调研报告.doc
  12. 数据结构课程 -- 学期总结
  13. CentOS实现双网卡网络共享
  14. 我的世界修改服务器头像,我的世界头像
  15. git提交代码失败 ‘“node“‘ �����ڲ����ⲿ���Ҳ���ǿ����еij������������ļ��� 解决方法
  16. android usb 投电视盒子,电脑还可以管理电视盒子?这样做就可以!
  17. DataX--异构数据源数据交换工具
  18. 吐血整理:手拿几个大厂offer的秘密武器!(免费领取)
  19. package.json中安装包的版本说明和符号说明
  20. java算法--冒泡算法

热门文章

  1. PPT分享第01季-226套多种风格模板
  2. aria2c的参数帮助
  3. P13 正交向量和正交子空间【线性代数】
  4. STM32F103ZET6学习记录-串口通信部分
  5. 网络安全(黑客)工具
  6. 云课堂智慧职教答案python_智慧职教云课堂Python程序设计答案
  7. 青岛旅行规划及玩后感
  8. sql存储过程的创建与调用
  9. 4.2 链路聚合:负载均衡
  10. 啊哈C!思考快你一步——用编程轻松提升逻辑力