CALL 一次 就會把地址 存入棧 然后 跳轉執行, 運行到 RET 就會從 棧中取出 地址, 返回CALL 的地方。
CALL 和 RET 應該是 成對的關系。沒錯吧? C 就是這么做的。
然后,你 CALL 一個函數, 這個函數,里面還要 調用 另一個函數,
這個時候,應該 CALL 然后, CALL 然后 RET 然后 RET 返回最初的地方對不對?
那么,我簡單點,不要CALL 直接JMP可以么? CALL JMP RET 是不是結果一樣?
再舉個簡單的例子吧
就是我之前舉的那個例子:
SEND_HALF_BCD:
ANL A,#0FH
ORL A,#30H
SEND_BYTE:
JNB TI,$
CLR TI
MOV SBUF,A
RET
這是一個復合函數,
CALL SEND_HALF_BCD 就能把 半個BCD 轉成 ASCCII 發出去。
CALL SEND_BYTE 就能直接把 一個字節 發出去,這個能理解么?
到這里為止,是不是沒有問題? 能理解么? 能的話,我們往下看。
換個寫法:
SEND_HALF_BCD:
ANL A,#0FH
ORL A,#30H
CALL SEND_BYTE
RET
SEND_BYTE:
JNB TI,$
CLR TI
MOV SBUF,A
RET
這樣,徹底拆成兩個函數,你能看明白么?
作用和剛才一樣,這是純C的寫法。 你比較喜歡這樣寫是么?
此時如果 CALL SEND_HALF_BCD
這就是你認為應該的, 兩次CALL 兩次RET 對吧?
然后,我們再換個寫法:
SEND_BYTE:
JNB TI,$
CLR TI
MOV SBUF,A
RET
SEND_HALF_BCD:
ANL A,#0FH
ORL A,#30H
LJMP SEND_BYTE
這樣, CALL SEND_HALF_BCD 有沒有問題? 假如你說有問題…… 那么,我們換個個。
SEND_HALF_BCD:
ANL A,#0FH
ORL A,#30H
LJMP SEND_BYTE
SEND_BYTE:
JNB TI,$
CLR TI
MOV SBUF,A
RET
這樣總沒問題了吧?
匯編之所以比C 效率高,就是可以避免無意義的 RET。 節約非必要的 RET 是提高效率的一種必要手段。這真的是基礎中的基礎了……
|