慎用51微控制器中的RET指令

2021-06-01 10:09:06 字數 1236 閱讀 8294

題目:已知有四個按鍵依次連線微控制器中的p3口的0到3的io口,有四個led燈連線p1的0到3 io口,寫一程式,滿足以下條件:當按下按乙個按鍵,對應的led會發亮,比如

按下p3.0的按鍵,連線p1.0的led就發亮。y

以下是我同學編寫的程式:

org 0000h

mov p1,#0ffh

loop:

jnb p3.0,led1;*

jnb p3.1,led2;*

jnb p3.2,led3;*

jnb p3.3,led4;*

ljmp loop

led1:

clr p1.0

retled2:

clr p1.1

retled3:

clr p1.2

retled4:

clr p1.3

retend

程式的意圖是,製造乙個死迴圈,不斷檢查按鍵是否按下,如果按下,就令對應的燈亮。程式經過測試,能夠滿足題目的要求。

但是,問題出現在上面帶*號的那一部分**,程式意圖是想要當p3的某個位為0的時候,就呼叫led燈的子程式,執行clr p1.0語句,再返回到原來程式呼叫子程式的地方繼續執行**。

我對的子程式的理解是:在乙個地方啟動一段**,當這段**執行完畢之後,就返回到原來的地方繼續執行剩下的**。

那麼cpu微控制器是如何返回原來的位址的呢?

首先,當程式執行到a處進入子程式時,將a的下乙個條指令(即pc+2所指的地方)壓入棧中,即將棧指標sp+1,pcl進棧,sp再加1,pch進棧。

然後,把pc的值改為子程式**的入口。

子程式執行完畢之後,從棧中彈出原來的pc值,賦值給當前的pc暫存器。

最後,程式返回到原來呼叫子程式的地方的下一條指令繼續執行。

(詳細步驟請檢視ret和acall,lcall指令)

上面的**很明顯想呼叫乙個子程式,但是51微控制器中,只有acall和lcall指令會在跳轉前講pc+2值壓棧,其他跳轉指令都不會。

**中使用了jnb作為跳轉指令,所以並沒有壓棧,但是當跳轉之後遇到ret,還是一如既往地彈棧,這樣,只有出,沒有進,會導致堆疊不平衡。

但為什麼這個程式依然有效呢?

這個因為sp初始指標指向了乙個空白的單元(全是0),所以,當遇到ret後,把pc暫存器給初始化,程式由頭開始重新執行,陰差陽錯地滿足的題目的要求。

所以ret指令必須和acall和lcall配套使用,才能組成為真正意義上的子程式

51微控制器系列 基礎指令

這學期開始學習51微控制器,感覺比彙編簡單,關鍵是51的彙編有乙個好的ide,練習起來也比較方便,這個系列主要記錄51的學習經驗。下面是基礎指令的練習 org 0000h ljmp main org 0030h main clr c cy 0 setb c cy 1 mov a,1111 0000b...

51微控制器

數碼管顯示幾乎是每次藍橋杯微控制器設計與開發組競賽的必考部分,相對於使用lcd1602作為顯示裝置,使用數碼管來顯示能夠更好的考察參賽選手的微控制器基本功,因為ct107d開發平台的設計使得數碼管的顯示不僅牽扯到數碼管顯示的 基本內容,還涉及到74hc573鎖存器,74hc02異或門,74hc138...

51微控制器

建立乙個自定義列表 如何建立乙個註腳 注釋也是必不可少的 katex數學公式 新的甘特圖功能,豐富你的文章 uml 圖表 flowchart流程圖 匯出與匯入 1.供電電源 一般開發板上提供兩種供電方式,usb供電和專用電源供電。使用usb供電你只要用一根usb線將開發板usb電源介面與電腦的usb...