1. 程式人生 > >51中ret和reti的區別

51中ret和reti的區別

今天閱讀巨龍公司系統整合開發部 楊屹 的《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。
 

參考連結:

相關推薦

51retreti區別

今天閱讀巨龍公司系統整合開發部 楊屹 的《uCOS51移植心得》時看到一句話:RETI指令復位中斷系統,RET則沒有。實踐表明,對於MCS-51,用子程式呼叫入棧,用中斷返回指令RETI出棧是沒有問題的,反之中斷入棧RET出棧則不行。總之,對於入棧,子程式呼叫與中斷呼叫效果

mybatis的#$的區別

背景 插入 trac sql註入 -m .com article 參數 -s 1. #將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #user_id#,如果傳入的值是111,那麽解析成sql時的值為order by "111", 如果傳

hibernatehql語句listiterate區別

每次 hibernate 寫入 所有 讀取 條件 iter 查詢 hql 1.使用list()方法獲取查詢結果,每次發出一條語句,獲取全部數據。2.使用iterate()方法獲取查詢結果,先發出一條SQL語句用來查詢滿足條件數據的id,然後依次按照這些id查詢記錄,也就是要

javaArrayListLinkedList區別

插入 list 新的 查找 arr tro 基於 列表 時間復雜度 ArrayList和LinkedList最主要的區別是基於不同數據結構 ArrayList是基於動態數組的數據結構,LinkedList基於鏈表的數據結構,針對這點,從時間復雜度和空間復雜度來看主要區別:

mysqlreplicate_wild_do_tablereplicate_do_db區別

lan rep cati mil 多人 pan think lte 避免 使用replicate_do_db和replicate_ignore_db時有一個隱患,跨庫更新時會出錯。 如在Master(主)服務器上設置 replicate_do_db=test(my.conf

linux ll ls 區別

彩色 顯示文件 時間排序 linux 常用 所有 數字 名稱 sub ll 列出來的結果詳細,有時間,是否可讀寫等信息 ,象windows裏的 詳細信息ls 只列出文件名或目錄名 就象windows裏的 列表ll -t 是降序, ll -t | tac 是升序 ll不是

jsdecodeURI()encodeURI()區別,decodeURIComponentencodeURIComponent區別

nbsp sch www 問題 encode 替換 副本 字符替換 序列 decodeURI()定義和用法:decodeURI()函數可對encodeURI()函數編碼過的URI進行解碼.語法:decodeURI(URIstring)參數描述:URIstring必需,一個字

HTP協議URIURL區別

int 名稱 net form 打開 文件路徑 指定 支持 地址 URL(uniform resource location ):統一資源定位符 URI(uniform resource identifier):統一資源標誌符 URI:可以表示一個域,也可以表示一個

mysqlvarcharchar區別(思維導圖整理)

var 但是 系統 mysql 由於 varchar .html nbsp 了解   由於mysql一直是我的弱項(其實各方面我都是很弱的),所以最近在看msyql,正好看到varchar和char區別,所以整理一下,便於以後遺忘。      0.0圖片已經說明一切,但是系

JavaScriptNullundefind區別

cdc 如何 undefine 只有一個 som pre cnblogs 定義 報錯 公眾號原文 Javascript有5種基本類型:Boolean,Number,Null,Undefined,String;和一種復雜類型:Object(對象); undef

淺談 Mybatis的 ${ } #{ }的區別

mybatis sql註入 語句 nbsp 之前 com pre 預編譯 sql 語句 一、舉例說明 1 select * from user where name = "dato"; 2 3 select * from user where name = #

mysql deletetrncate區別

重新 sql delet use 它的 刪除 掃描 進行 from mysql中刪除表記錄delete from和truncate table的用法區別: MySQL中有兩種刪除表中記錄的方法:(1)delete from語句,(2)truncate table語句。 d

VBA字符串連接/字符串拼接“&”“+”的區別

運算符 強制 clear arch tle .com 字符串連接 ive 數字 VBA中字符串連接/字符串拼接中“&”和“+”的區別 在VBA中用於字符串連接的只有“&”和“+”兩種運算符。 1、“&”是強制性連接,就是不管什麽都連接。 2、

說一下PHPdie()exit()區別

選擇 fop class 系統 light 常用 spa ner 終端 PHP手冊:die()Equivalent to exit()。 說明:die()和exit()都是中止腳本執行函數;其實exit和die這兩個名字指向的是同一個函數,die()是exit()函數的別名

Mysqldatetimetimestamp區別

sta mysql -m 時區 日期 timestamp 適應 tex 區別 DATETIME日期和時間的組合。支持的範圍是‘1000-01-01 00:00:00‘到‘9999-12-31 23:59:59‘。MySQL以‘YYYY-MM-DD HH:MM:SS‘格式顯示

jsopener parent區別

pen window ner win 就是 引用 窗口 iframe 彈出 1、opener即誰打開我的,比如A頁面利用window.open彈出了B頁面窗口,那麽A頁面所在窗口就是B頁面的opener,在B頁面通過opener對象可以訪問A頁面。 2、parent表示父窗

【轉載】詳解 $_SERVER 函數QUERY_STRINGREQUEST_URI區別

host dex 執行 sel 實例 server 文件 uri cal 實例:1,http://localhost/aaa/ (打開aaa中的index.php)結果:$_SERVER[‘QUERY_STRING‘] = "";$_SERVER[‘REQUEST_URI‘

Python__repr____str__區別

close 提示 bsp pri urn 創建 pla 不同 並不是 1.先看區別 1 class Test(object): 2 def __init__(self, value=‘hello, world!‘): 3 self.data

Pythonis==的區別

int 要素 com 分別是 htm python get 參考資料 元組類型 Python中有很多運算符,今天我們就來講講is和==兩種運算符在應用上的本質區別是什麽。 在講is和==這兩種運算符區別之前,首先要知道Python中對象包含的三個基本要素,分別是:id(身份

javaequals==的區別

ML int .net 重寫 com span double str 文獻 (表達可能存在錯誤,需進一步完善) 1、首先搞清楚java裏面的數據類型包括: 基本數據類型和引用數據類型 2、數據類型 基本數據類型: byte,short(2 byte),int(4 byt