找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
123
返回列表 發(fā)新帖
樓主: newlined
打印 上一主題 下一主題
收起左側(cè)

請教各位大神一個匯編語言堆棧大小計算的問題

[復(fù)制鏈接]
81#
ID:624769 發(fā)表于 2022-10-25 14:38 | 只看該作者
newlined 發(fā)表于 2022-10-25 13:50
你好,這個例子,我一直試圖理解,但我沒有想通。我是這樣理解的,LCALL 一個函數(shù)時,堆棧會保存當(dāng)前調(diào)用 ...

CALL 一次,就會把當(dāng)前地址放入  棧   然后跳轉(zhuǎn),讀到RET  從 棧里 讀出地址, 然后返回  CALL 的地方。
回復(fù)

使用道具 舉報

82#
ID:384109 發(fā)表于 2022-10-25 14:43 | 只看該作者
lcall和ljmp是不同的機(jī)制,lcall會壓棧,ljmp不對棧操作,lcal必須有ret,ljmp一定不能有ret,51除了硬件自動壓棧的以外,其他都是人工壓棧的
回復(fù)

使用道具 舉報

83#
ID:624769 發(fā)表于 2022-10-25 14:58 | 只看該作者
newlined 發(fā)表于 2022-10-25 13:50
你好,這個例子,我一直試圖理解,但我沒有想通。我是這樣理解的,LCALL 一個函數(shù)時,堆棧會保存當(dāng)前調(diào)用 ...

CALL 一次  就會把地址  存入棧  然后  跳轉(zhuǎn)執(zhí)行, 運(yùn)行到 RET 就會從 棧中取出 地址, 返回CALL 的地方。
CALL 和 RET  應(yīng)該是 成對的關(guān)系。沒錯吧? C 就是這么做的。

然后,你 CALL 一個函數(shù), 這個函數(shù),里面還要 調(diào)用 另一個函數(shù),  
這個時候,應(yīng)該  CALL  然后, CALL  然后 RET  然后 RET  返回最初的地方對不對?
那么,我簡單點(diǎn),不要CALL 直接JMP可以么?  CALL   JMP   RET  是不是結(jié)果一樣?

再舉個簡單的例子吧

就是我之前舉的那個例子:

SEND_HALF_BCD:
ANL   A,#0FH
ORL   A,#30H
SEND_BYTE:
JNB     TI,$
CLR     TI
MOV   SBUF,A
RET

這是一個復(fù)合函數(shù),

CALL SEND_HALF_BCD  就能把 半個BCD 轉(zhuǎn)成 ASCCII 發(fā)出去。
CALL SEND_BYTE      就能直接把 一個字節(jié) 發(fā)出去,這個能理解么?

到這里為止,是不是沒有問題? 能理解么?  能的話,我們往下看。

換個寫法:
SEND_HALF_BCD:
ANL   A,#0FH
ORL   A,#30H
CALL        SEND_BYTE
RET

SEND_BYTE:
JNB     TI,$
CLR     TI
MOV   SBUF,A
RET

這樣,徹底拆成兩個函數(shù),你能看明白么?  
作用和剛才一樣,這是純C的寫法。 你比較喜歡這樣寫是么?
此時如果 CALL SEND_HALF_BCD
這就是你認(rèn)為應(yīng)該的, 兩次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。 節(jié)約非必要的 RET 是提高效率的一種必要手段。這真的是基礎(chǔ)中的基礎(chǔ)了……
回復(fù)

使用道具 舉報

84#
ID:384109 發(fā)表于 2022-10-25 15:17 | 只看該作者
樓上的例子有點(diǎn)特例了,像send_byte可以作為一個公用的子程序,如果用jmp,ret會不好控制,除非只有一個地方專門調(diào)用,即使是匯編,最好也是模塊話,條理會清晰很多
回復(fù)

使用道具 舉報

85#
ID:883242 發(fā)表于 2022-10-25 18:44 | 只看該作者
188610329 發(fā)表于 2022-10-25 14:58
CALL 一次  就會把地址  存入棧  然后  跳轉(zhuǎn)執(zhí)行, 運(yùn)行到 RET 就會從 棧中取出 地址, 返回CALL 的地方。 ...
  1. %*DEFINE(SEND_BYTE)(
  2.     JNB     TI,$
  3.     CLR     TI
  4.     MOV   SBUF,A
  5. )
  6. SEND_HALF_BCD:
  7.     ANL   A,#0FH
  8.     ORL   A,#30H
  9.     %SEND_BYTE       
復(fù)制代碼


我這個效率比你的還要高,連LJMP都省掉了,你的匯編還沒學(xué)到家。

我用的是Intel MCS-51 MACRO ASSEMBLER, V2.2,如果用Keil A51編譯不通過請查手冊。
回復(fù)

使用道具 舉報

86#
ID:624769 發(fā)表于 2022-10-25 19:45 | 只看該作者
Hephaestus 發(fā)表于 2022-10-25 18:44
我這個效率比你的還要高,連LJMP都省掉了,你的匯編還沒學(xué)到家。

我用的是Intel MCS-51 MACRO ASS ...

人家問 CALL 和 RET,  你發(fā)個 沒CALL 沒 RET 的 代碼
回復(fù)

使用道具 舉報

87#
ID:227818 發(fā)表于 2022-10-26 02:20 | 只看該作者
Hephaestus 發(fā)表于 2022-10-25 18:44
我這個效率比你的還要高,連LJMP都省掉了,你的匯編還沒學(xué)到家。

我用的是Intel MCS-51 MACRO ASS ...

您這個看起來更簡單,俗話說人外有人,天外有天,但我現(xiàn)在是更看不懂,感謝大家提供不同的代碼讓我們這些初學(xué)者揣摩。
回復(fù)

使用道具 舉報

88#
ID:883242 發(fā)表于 2022-10-26 03:38 | 只看該作者
newlined 發(fā)表于 2022-10-26 02:20
您這個看起來更簡單,俗話說人外有人,天外有天,但我現(xiàn)在是更看不懂,感謝大家提供不同的代碼讓我 ...

這不是“人外有人,天外有天”的問題,時間久了你就能明白最重要的學(xué)問是數(shù)學(xué)和英語。
回復(fù)

使用道具 舉報

89#
ID:624769 發(fā)表于 2022-10-26 20:02 | 只看該作者
Hephaestus 發(fā)表于 2022-10-26 03:38
這不是“人外有人,天外有天”的問題,時間久了你就能明白最重要的學(xué)問是數(shù)學(xué)和英語。

數(shù)一數(shù)你這編譯出來多少字節(jié), 在來講話
先不說人家問的  CALL RET , 你 CALL 和 RET 呢?  忘帶了?
其次, define 到底是什么? 你應(yīng)該很清楚,沒必要再這里%。
你怎么不把所有代碼  define 只后,你還能 只要一句代碼  就能把智能蔽障小車寫出來呢?
%
回復(fù)

使用道具 舉報

90#
ID:883242 發(fā)表于 2022-10-26 20:18 | 只看該作者
188610329 發(fā)表于 2022-10-26 20:02
所以,先把數(shù)學(xué)學(xué)好, 數(shù)一數(shù)你這編譯出來多少字節(jié), 在來講話, 然后把語文學(xué)好,學(xué)學(xué)怎么講話。
先不 ...

教你一句成語——不屑一顧。
回復(fù)

使用道具 舉報

91#
ID:624769 發(fā)表于 2022-10-27 00:20 | 只看該作者
Hephaestus 發(fā)表于 2022-10-26 20:18
教你一句成語——不屑一顧。

教你一句成語——夜郎自大。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表