51 單片機彙編語言:利用 RET 指令實現多路分支

有這樣一個問題:


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


已知程序執行前有 A = 02H,SP = 52H,(51H) = FFH,(52H) = FFH。


執行下列程序:


    POP   DPH

    POP   DPL

    MOV   DPTR, #4000H  

    RL    A

    MOV   B, A

    MOVC  A, @A + DPTR

    PUSH  A

    MOV   A, B

    INC   A

    MOVC  A, @A + DPTR

    PUSH  A

    RET


    ORG   4000H

    DB    10H, 80H, 30H, 50H, 30H, 50H


求程序執行後:


A=(  )H、SP=(  )H、(51H) =(  )H、(52H)=(  )H、PC=(    )H。


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


這個問題,在百度知道出現過很多次,搜一下,就會出來幾十個鏈接。


但是回答正確的,確實不多。


有的提問者,好像是說,這是什麼學校教材上的習題。


在這個程序中,寫錯了兩條指令:


非法指令:PUSH  A

應該寫成:PUSH  ACC


做爲教材來說,這可是一個 BUG 啊,呵呵



這個程序,是利用 RET 指令來進行多路分支。


程序中,有兩條查表指令:MOVC  A, @A + DPTR,


當 A = 0 時,將從 4000H 處,先後讀出 10H、80H;

當 A = 1 時,將從 4000H 處,先後讀出 30H、50H;

當 A = 2 時,將從 4000H 處,先後讀出 30H、50H。


本題目的條件已經給出:A = 02H,那麼就是讀出了 30H、50H。


讀出數據後,先後壓棧,再執行 RET。


RET 指令,就是把堆棧中的兩個字節,送到 PC。


那麼,PC = 5030H,就是這麼來的。


全部的空格,填寫如下:

A=(50)H、SP=(50)H、(51H) =(30)H、(52H)=(50)H、PC=(5030)H。


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


本程序,是個子程序結構,應該用 CALL 指令來調用。


在本程序開始處,用 POP 指令,拋棄了 CALL 自動保存的返回地址。


騰出了兩個字節的堆棧空間,又壓入兩字節數據,然後,再返回。


RET 返回指令,就會用剛剛壓入兩字節數據,當做返回地址。


本程序,是屬於偷樑換柱,還是移花接木 ?


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


下面逐條解釋一下:


    POP   DPH

    POP   DPL           ;彈出兩次,SP = SP - 2 = 50H


    MOV   DPTR, #4000H  

    RL    A             ;乘以2

    MOV   B, A          ;B = 04H


    MOVC  A, @A + DPTR  ;取出第4個字節30H

    PUSH  ACC           ;SP = SP + 1 = 51H, (51H)=30H


    MOV   A, B

    INC   A             ;A = 05H

    MOVC  A, @A + DPTR  ;取出第5個字節50H

    PUSH  ACC           ;SP = SP + 1 = 52H, (52H)=50H


    RET                 ;子程序返回指令



執行 RET 指令時,是從堆棧中彈出兩個字節到 PC 的高、低八位。


即:

(SP) → PCH,然後 SP - 1 → SP;

(SP) → PCL,然後 SP - 1 → SP。


即:

(52H) = 50H → PCH,SP = 51H

(51H) = 30H → PCL,SP = 50H


那麼,PC = 5030H,就是這麼來的。


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


進行多路分支,還有簡單一點的方法。


如,利用指令:JMP  @A + DPTR,就可以。


那麼,前面的程序,可以改爲:


    MOV   DPTR, #4000H  

    RL    A

    MOV   B, A

    MOVC  A, @A + DPTR 

    XCH   A, B


    INC   A

    MOVC  A, @A + DPTR ;先後讀出兩字節


    MOV   DPH, A       ;把讀出數據送到 DPTR

    MOV   DPL, B


    CLR   A            ;A=0

    JMP   @A + DPTR    ;以 DPTR 內容爲目的地,轉移


    ORG   4000H

    DB    10H, 80H, 30H, 50H, 30H, 50H


程序這樣寫,就不涉及堆棧了,也就沒有前一個程序那麼複雜的推導。


理解起來,可以輕鬆些。


這個程序,沒有使用 RET 指令,那麼,就不要用 CALL 來調用了。


要用 JMP 指令來應用本程序。


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

題目鏈接:


http://zhidao.baidu.com/question/62813244.html

http://zhidao.baidu.com/question/508425830.html

http://zhidao.baidu.com/question/586060870.html

http://zhidao.baidu.com/question/205965529.html


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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章