欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 11195|回復(fù): 91
收起左側(cè)

請(qǐng)教各位大神一個(gè)匯編語(yǔ)言堆棧大小計(jì)算的問(wèn)題

[復(fù)制鏈接]
ID:227818 發(fā)表于 2022-7-12 06:34 | 顯示全部樓層 |閱讀模式
我有一個(gè)主程序A(是51單片機(jī)的匯編),在STC 8H上跑,這個(gè)主程序A調(diào)用了子程序A1,A1又調(diào)用了A2,A2又調(diào)用了A3,即A->A1->A2->A3。中斷用了5個(gè),可以定義成中斷B,C,D,E,F(xiàn)。其中中斷B,C是高級(jí)中斷,D,E,F(xiàn)是低級(jí)中斷。所有中斷中都是PUSH ACC,PUSH PSW,沒(méi)有再PUSH其他寄存器,出中斷時(shí)POP PSW ,POP ACC。中斷B中,調(diào)用了子程序B1,B1又調(diào)用了B2即B-B1->B2。C中斷中沒(méi)有調(diào)用其他子程序。D中斷中調(diào)用了子程序D1,D1又調(diào)用了D2,即D->D1-D2。E中斷中調(diào)用了子程序E1,E1又調(diào)用了E2,E2又調(diào)用了E3,即E->E1->E2-E3。所有子程序都是簡(jiǎn)單的對(duì)單片機(jī)的端口進(jìn)行操作,即置高或低,子程序沒(méi)有用堆棧傳遞參數(shù)。按照我的理解,考慮一個(gè)最復(fù)雜的情況,主程序在調(diào)用A3時(shí),堆棧用了6個(gè)字節(jié),這時(shí)發(fā)生E中斷,E中斷在調(diào)用E3時(shí),堆棧用了8個(gè)字節(jié),這是發(fā)生B中斷,在B中斷調(diào)用B2時(shí),堆棧用了6個(gè)字節(jié),這樣堆棧最多用20個(gè)字節(jié)就可以了,但在實(shí)際情況中,單片機(jī)不時(shí)會(huì)死機(jī).這個(gè)程序原先不是我寫的,我不過(guò)做了一點(diǎn)修改,即在中斷E中加了一個(gè)子程序E3。以前堆棧留的比較小,只有20個(gè)字節(jié),后來(lái)我又找了幾個(gè)加上了,但還是不大。現(xiàn)在我懷疑是堆棧溢出了,請(qǐng)問(wèn)我堆棧大小的計(jì)算對(duì)嗎?衷心感謝
回復(fù)

使用道具 舉報(bào)

ID:887371 發(fā)表于 2022-7-12 12:03 | 顯示全部樓層
1.51的任何子程序都需要通過(guò)堆棧傳遞PC值,最少2字節(jié)。
2.51的中斷子程序通過(guò)堆棧傳遞PC、ACC、PSW ,最少4字節(jié)。
3.中斷內(nèi)部調(diào)用子程序算情形1,最少2字節(jié)。

你的代碼有2級(jí)中斷調(diào)用,情形1調(diào)用算6級(jí),所以最少20字節(jié)(2*4+6*2)。
但上述是最理想的情況。我們一般按10級(jí)情形1算,但情形1算5字節(jié),預(yù)留50字節(jié)堆棧。

評(píng)分

參與人數(shù) 1黑幣 +15 收起 理由
newlined + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:401564 發(fā)表于 2022-7-12 12:26 | 顯示全部樓層
8051是軟件堆棧,如果不是刻意去填滿它,堆棧基本上是不會(huì)有問(wèn)題的
卡死的問(wèn)題不一定是堆棧的問(wèn)題,可能是中斷太多,而且中斷觸發(fā)間隔時(shí)間太短
比如說(shuō):
1,ADC中你調(diào)用了某個(gè)子程序,ADC執(zhí)行的總時(shí)長(zhǎng)是5mS,ADC中斷你又設(shè)定成最高優(yōu)先等級(jí),而ADC中斷間隔是1mS
2,定時(shí)器中斷是2mS的
那么,這個(gè)程序就一直在ADC和定時(shí)器之間運(yùn)行了,主程序基本是不會(huì)執(zhí)行的

評(píng)分

參與人數(shù) 1黑幣 +15 收起 理由
newlined + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-12 14:21 | 顯示全部樓層
datouyuan 發(fā)表于 2022-7-12 12:03
1.51的任何子程序都需要通過(guò)堆棧傳遞PC值,最少2字節(jié)。
2.51的中斷子程序通過(guò)堆棧傳遞PC、ACC、PSW ,最少 ...

謝謝您的回復(fù),我算的是最多需要20字節(jié),您算的最少需要20字節(jié)
我是這樣理解的同為高級(jí)的2個(gè)中斷B,C,同一時(shí)刻只能有一個(gè)中斷響應(yīng),C中斷響應(yīng),堆棧占用2個(gè)字節(jié),B中斷響應(yīng),最多占用6個(gè)字節(jié),所以按B中斷記,D,E,F三個(gè)低級(jí)中斷,它們?nèi)齻(gè)同一時(shí)刻只有1個(gè)被CPU響應(yīng),主貼中忘記說(shuō)了,F(xiàn)中斷內(nèi)沒(méi)有子程序,按子程序調(diào)用最深的E中斷算,低級(jí)中斷最多需要8個(gè)字節(jié),主程序中子程序調(diào)用最多需要6個(gè)字節(jié),這樣需要20個(gè)字節(jié)就可以了。按照您的計(jì)算,我肯定是哪里理解錯(cuò)了,錯(cuò)在那里,麻煩您再說(shuō)一下,我在這方面是半路出家,有些方面理解不透,謝謝。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-12 14:28 | 顯示全部樓層
Y_G_G 發(fā)表于 2022-7-12 12:26
8051是軟件堆棧,如果不是刻意去填滿它,堆棧基本上是不會(huì)有問(wèn)題的
卡死的問(wèn)題不一定是堆棧的問(wèn)題,可能是中 ...

謝謝您的回復(fù),我明白了您的意思,您是說(shuō),中斷觸發(fā)間隔的時(shí)間短,而中斷本身執(zhí)行的時(shí)間長(zhǎng),結(jié)果就是CPU在中斷之間運(yùn)行,一個(gè)中斷執(zhí)行完,馬上又去響應(yīng)另一個(gè)中斷,然后又去響應(yīng)前一個(gè)中斷,沒(méi)有時(shí)間去執(zhí)行主程序,我按您的思路拿示波器跟蹤下,看看每一個(gè)中斷需要多少時(shí)間。
回復(fù)

使用道具 舉報(bào)

ID:1006814 發(fā)表于 2022-7-12 15:00 | 顯示全部樓層
每次中斷,自動(dòng)入棧一個(gè)PC寄存器,具體幾個(gè)字節(jié)我忘了,然后中斷返回的時(shí)候再自動(dòng)出棧,樓主沒(méi)考慮這個(gè),所以可能會(huì)亂。

評(píng)分

參與人數(shù) 1黑幣 +15 收起 理由
newlined + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-12 15:24 | 顯示全部樓層
hb_lhw 發(fā)表于 2022-7-12 15:00
每次中斷,自動(dòng)入棧一個(gè)PC寄存器,具體幾個(gè)字節(jié)我忘了,然后中斷返回的時(shí)候再自動(dòng)出棧,樓主沒(méi)考慮這個(gè),所 ...

您說(shuō)的應(yīng)該是程序寄存器,也就是PC寄存器,它是16位的,占用2個(gè)字節(jié),按說(shuō)我已經(jīng)考慮到了。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-12 15:27 | 顯示全部樓層
datouyuan 發(fā)表于 2022-7-12 12:03
1.51的任何子程序都需要通過(guò)堆棧傳遞PC值,最少2字節(jié)。
2.51的中斷子程序通過(guò)堆棧傳遞PC、ACC、PSW ,最少 ...

我剛才又想到,是不是中斷嵌套時(shí),堆棧需要消耗更多的字節(jié)?中斷嵌套時(shí)堆棧消耗的字節(jié)是怎樣計(jì)算的?
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-12 15:44 | 顯示全部樓層
本帖最后由 newlined 于 2022-7-12 15:47 編輯
Y_G_G 發(fā)表于 2022-7-12 12:26
8051是軟件堆棧,如果不是刻意去填滿它,堆棧基本上是不會(huì)有問(wèn)題的
卡死的問(wèn)題不一定是堆棧的問(wèn)題,可能是中 ...

您好,我剛才拿示波器跟蹤了一下,一共5個(gè)中斷,2個(gè)中斷是1毫秒一次,一個(gè)外部中斷是20毫秒到100毫秒一次,這3個(gè)1個(gè)請(qǐng)問(wèn)-中斷的時(shí)間在5微妙到10微妙之間,應(yīng)該沒(méi)有問(wèn)題。還有一個(gè)是30毫秒1次,執(zhí)行時(shí)間是10微秒,也沒(méi)有問(wèn)題,執(zhí)行時(shí)間比較長(zhǎng)的是一個(gè)掉電中斷,是高級(jí)中斷,執(zhí)行時(shí)間10毫秒,這個(gè)中斷執(zhí)行完就不再執(zhí)行其他語(yǔ)句了,單片機(jī)就等著掉電了。按說(shuō)也不影響主程序的運(yùn)行
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-7-12 16:25 | 顯示全部樓層
是不是堆棧大小的問(wèn)題, 用KEIL 編譯后,仿真一下,看一下 SP_max 就知道了。有什么好算得?

我現(xiàn)在好奇的是,你確定是堆棧問(wèn)題? 你那么多中斷 你居然   都是只 PUSH ACC 和 PSW 的? 你不用 R0~R7 的? 不用 B 的?  不用 DPTR 的? 這些只要有一個(gè),你該P(yáng)USH 的沒(méi)有PUSH 都會(huì)有可能造成發(fā)生過(guò) 中斷后,程序出現(xiàn)錯(cuò)誤,最終跑飛。

評(píng)分

參與人數(shù) 1黑幣 +15 收起 理由
newlined + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:401564 發(fā)表于 2022-7-12 16:56 | 顯示全部樓層
newlined 發(fā)表于 2022-7-12 14:28
謝謝您的回復(fù),我明白了您的意思,您是說(shuō),中斷觸發(fā)間隔的時(shí)間短,而中斷本身執(zhí)行的時(shí)間長(zhǎng),結(jié)果就是CPU ...

大概就是這么個(gè)意思了
也就是說(shuō)程序是在中斷之間來(lái)回跑的
主程序幾乎沒(méi)有執(zhí)行的時(shí)間
為什么要在中斷中執(zhí)行那么多功能呢?能不能放在主程序執(zhí)行呢?
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-12 17:03 | 顯示全部樓層
Y_G_G 發(fā)表于 2022-7-12 16:56
大概就是這么個(gè)意思了
也就是說(shuō)程序是在中斷之間來(lái)回跑的
主程序幾乎沒(méi)有執(zhí)行的時(shí)間

這個(gè)程序是20年前別人編寫的,我現(xiàn)在接手維護(hù),整個(gè)程序還沒(méi)有吃透。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-12 17:13 | 顯示全部樓層
Y_G_G 發(fā)表于 2022-7-12 16:56
大概就是這么個(gè)意思了
也就是說(shuō)程序是在中斷之間來(lái)回跑的
主程序幾乎沒(méi)有執(zhí)行的時(shí)間

大約1小時(shí)前回復(fù)過(guò),不知道回帖為什么沒(méi)有了。今天下午我拿示波器跟蹤了各個(gè)中斷的執(zhí)行時(shí)間,有2個(gè)是1毫秒1次的中斷,執(zhí)行時(shí)間在10微妙左右,1個(gè)是30毫秒的中斷,執(zhí)行時(shí)間是10微妙多一點(diǎn),一個(gè)外部中斷,20毫秒到100毫秒一次,執(zhí)行時(shí)間在8微妙左右,應(yīng)該都可以,不會(huì)引起主程序執(zhí)行時(shí)間的不足,一個(gè)掉電中斷,是高級(jí)中斷,執(zhí)行時(shí)間10毫秒,這個(gè)按說(shuō)也不影響主程序的運(yùn)行,因?yàn)檫@個(gè)中斷執(zhí)行完,就等著掉電了,不再執(zhí)行其他語(yǔ)句了。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-12 17:18 | 顯示全部樓層
188610329 發(fā)表于 2022-7-12 16:25
是不是堆棧大小的問(wèn)題, 用KEIL 編譯后,仿真一下,看一下 SP_max 就知道了。有什么好算得?

我現(xiàn)在好奇 ...

這個(gè)程序是20年前別人寫的,我接手維護(hù),小改下,不好動(dòng)架構(gòu)。
回復(fù)

使用道具 舉報(bào)

ID:887371 發(fā)表于 2022-7-12 17:23 | 顯示全部樓層
newlined 發(fā)表于 2022-7-12 14:21
謝謝您的回復(fù),我算的是最多需要20字節(jié),您算的最少需要20字節(jié)
我是這樣理解的同為高級(jí)的2個(gè)中斷B ...
考慮一個(gè)最復(fù)雜的情況,主程序在調(diào)用A3時(shí),堆棧用了6個(gè)字節(jié),這時(shí)發(fā)生E中斷,E中斷在調(diào)用E3時(shí),堆棧用了8個(gè)字節(jié),這是發(fā)生B中斷,在B中斷調(diào)用B2時(shí),堆棧用了6個(gè)字節(jié),這樣堆棧最多用20個(gè)字節(jié)就可以了

A到A3,是函數(shù)調(diào)用3級(jí),最少6字節(jié)。
E中斷,是中斷函數(shù)調(diào)用,最少4字節(jié)。
E到E3,是函數(shù)調(diào)用3級(jí),最少6字節(jié)。
B中斷,是中斷函數(shù)調(diào)用,最少4字節(jié)。
B到B2,是函數(shù)調(diào)用2級(jí),最少4字節(jié)。
最少24字節(jié)。

不需要按上述計(jì)算,堆棧就是按函數(shù)調(diào)用深度和中斷函數(shù)調(diào)用深度估算。
函數(shù)調(diào)用深度8級(jí),最少占用16(2*8)字節(jié)。
中斷函數(shù)調(diào)用深度2級(jí),最少占用8(4*2)字節(jié)。
我提到的3點(diǎn)原則只考慮了PCH PCL ACC PSW的保存、恢復(fù),是最低要求的情形。有些應(yīng)用還要考慮DPTR、B、R0~R7的保存、恢復(fù),所以堆棧需求會(huì)明顯大于24個(gè)字節(jié)。

評(píng)分

參與人數(shù) 1黑幣 +15 收起 理由
newlined + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:887371 發(fā)表于 2022-7-12 17:35 | 顯示全部樓層
C51中斷中使用函數(shù)是很不好的習(xí)慣。
你把中斷中的函數(shù)改成不是函數(shù),以代碼空間換時(shí)間和RAM。
應(yīng)該能解決問(wèn)題。

評(píng)分

參與人數(shù) 1黑幣 +15 收起 理由
newlined + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:401564 發(fā)表于 2022-7-12 18:20 | 顯示全部樓層
newlined 發(fā)表于 2022-7-12 17:13
大約1小時(shí)前回復(fù)過(guò),不知道回帖為什么沒(méi)有了。今天下午我拿示波器跟蹤了各個(gè)中斷的執(zhí)行時(shí)間,有2個(gè)是1毫 ...

所謂"死機(jī)"和中斷無(wú)法跳出,這不過(guò)是推測(cè)而已,說(shuō)不定可能就是其它的小問(wèn)題而已
匯編是很容易出問(wèn)題的
如果說(shuō)是以前的代碼是可以量產(chǎn)的,就說(shuō)明以前的代碼是沒(méi)有問(wèn)題的
重點(diǎn)看你的代碼會(huì)影響到哪些
如果不是什么商業(yè)機(jī)密,就把完整代碼上傳,大家一看就知道了
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-13 13:32 | 顯示全部樓層
188610329 發(fā)表于 2022-7-12 16:25
是不是堆棧大小的問(wèn)題, 用KEIL 編譯后,仿真一下,看一下 SP_max 就知道了。有什么好算得?

我現(xiàn)在好奇 ...

您好,以前的程序就是沒(méi)有對(duì)DPTR保護(hù)。看了您的發(fā)言后,我看了下程序,里邊的確用了DPTR,不知道為什么程序還可以運(yùn)行。工作寄存器的4個(gè)區(qū),有1個(gè)區(qū)是2個(gè)低級(jí)中斷公用的,這2個(gè)中斷不會(huì)同時(shí)響應(yīng),只用了R0和R1,每次用之前,都要先賦值,訪問(wèn)間接尋址的空間,所以不會(huì)沖突。B寄存器也用了,不知道為什么沒(méi)有保護(hù)。這個(gè)程序大幾千行,沒(méi)有文字的介紹資料,注釋也很少,估計(jì)不止一人維護(hù)過(guò).我還遠(yuǎn)沒(méi)有吃透.
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-7-13 13:44 | 顯示全部樓層
newlined 發(fā)表于 2022-7-13 13:32
您好,以前的程序就是沒(méi)有對(duì)DPTR保護(hù)。看了您的發(fā)言后,我看了下程序,里邊的確用了DPTR,不知道為什么程 ...

程序沒(méi)吃透的前提下, 最不變應(yīng)萬(wàn)變的做法,就是中斷里用了了什么, 進(jìn)入中斷前就 PUSH什么, 出中斷前 POP什么, 這是最笨,但也是最穩(wěn)妥的辦法。 等到吃透之后,可以選擇性的 PUSH 和 POP

評(píng)分

參與人數(shù) 1黑幣 +15 收起 理由
newlined + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-13 13:47 | 顯示全部樓層
datouyuan 發(fā)表于 2022-7-12 17:35
C51中斷中使用函數(shù)是很不好的習(xí)慣。
你把中斷中的函數(shù)改成不是函數(shù),以代碼空間換時(shí)間和RAM。
應(yīng)該能解決 ...

您好,您這一說(shuō),我意識(shí)到一個(gè)問(wèn)題,函數(shù)重入,這個(gè)程序編譯時(shí)曾經(jīng)出過(guò)這個(gè)警告,后來(lái)我把一個(gè)函數(shù)復(fù)制了一份,另起了一個(gè)名字,供不同的子程序還是中斷調(diào)用,現(xiàn)在是不是還有這個(gè)問(wèn)題?在keil c中也不能這么用嗎?
回復(fù)

使用道具 舉報(bào)

ID:887371 發(fā)表于 2022-7-13 15:12 | 顯示全部樓層
newlined 發(fā)表于 2022-7-13 13:47
您好,您這一說(shuō),我意識(shí)到一個(gè)問(wèn)題,函數(shù)重入,這個(gè)程序編譯時(shí)曾經(jīng)出過(guò)這個(gè)警告,后來(lái)我把一個(gè)函數(shù)復(fù)制了 ...

一般的C51函數(shù)是不支持再入的。
一個(gè)函數(shù)復(fù)制了一份,另起了一個(gè)名字

可以這樣解決(這個(gè)函數(shù)內(nèi)部不能有函數(shù)),但你必須確保業(yè)務(wù)邏輯不會(huì)有問(wèn)題。

中斷調(diào)用的函數(shù)一般只被中斷調(diào)用,所以沒(méi)有必要寫成函數(shù)。

評(píng)分

參與人數(shù) 1黑幣 +15 收起 理由
newlined + 15

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-13 15:42 | 顯示全部樓層
datouyuan 發(fā)表于 2022-7-12 17:35
C51中斷中使用函數(shù)是很不好的習(xí)慣。
你把中斷中的函數(shù)改成不是函數(shù),以代碼空間換時(shí)間和RAM。
應(yīng)該能解決 ...

您說(shuō)的對(duì),開始我并沒(méi)有理解您的意思,剛才看中斷中的函數(shù),我想到,假設(shè)在中斷中,我使用了R0,然后調(diào)用函數(shù),在函數(shù)中我又使用了R0,從函數(shù)返回后,R0的值肯定變了.好在我用R0都是用來(lái)訪問(wèn)間接尋址的地址,隨用隨賦值,要是用R0保存某個(gè)數(shù)據(jù)的話,調(diào)用函數(shù)前,可不可以PUSH到堆棧,調(diào)用函數(shù)后再POP?
回復(fù)

使用道具 舉報(bào)

ID:887371 發(fā)表于 2022-7-13 15:52 | 顯示全部樓層
newlined 發(fā)表于 2022-7-13 15:42
您說(shuō)的對(duì),開始我并沒(méi)有理解您的意思,剛才看中斷中的函數(shù),我想到,假設(shè)在中斷中,我使用了R0,然后調(diào)用 ...

當(dāng)然可以。但這又會(huì)增加堆棧需求。
匯編代碼要自己考慮如何保護(hù)現(xiàn)場(chǎng),恢復(fù)現(xiàn)場(chǎng)。

C51編譯器能根據(jù)上下文,自動(dòng)做好保護(hù)現(xiàn)場(chǎng),恢復(fù)現(xiàn)場(chǎng)。
好在我用R0都是用來(lái)訪問(wèn)間接尋址的地址,隨用隨賦值

你這種做法沒(méi)有用。這個(gè)操作不是原子操作,中斷會(huì)發(fā)生在操作中間,發(fā)生中斷后,不能恢復(fù)現(xiàn)場(chǎng)。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-13 16:11 | 顯示全部樓層
datouyuan 發(fā)表于 2022-7-13 15:52
當(dāng)然可以。但這又會(huì)增加堆棧需求。
匯編代碼要自己考慮如何保護(hù)現(xiàn)場(chǎng),恢復(fù)現(xiàn)場(chǎng)。

您是說(shuō)中斷自己不能恢復(fù)現(xiàn)場(chǎng),需要人為的PUSH,POP來(lái)恢復(fù)現(xiàn)場(chǎng)?而函數(shù)調(diào)用,C51的編譯器可以調(diào)用函數(shù)時(shí),用堆棧保存PC的值,調(diào)用完,函數(shù)執(zhí)行到RET,PC的值自動(dòng)恢復(fù),其他寄存器的值也自動(dòng)恢復(fù)?
回復(fù)

使用道具 舉報(bào)

ID:887371 發(fā)表于 2022-7-13 17:12 | 顯示全部樓層
newlined 發(fā)表于 2022-7-13 16:11
您是說(shuō)中斷自己不能恢復(fù)現(xiàn)場(chǎng),需要人為的PUSH,POP來(lái)恢復(fù)現(xiàn)場(chǎng)?而函數(shù)調(diào)用,C51的編譯器可以調(diào)用函數(shù)時(shí), ...

只有PC值能自動(dòng)恢復(fù),其它值得恢復(fù)要靠軟件操作。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-13 17:22 | 顯示全部樓層
是這樣,明天我仿真下,再仔細(xì)領(lǐng)會(huì)您的意思。
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-7-13 18:22 | 顯示全部樓層
newlined 發(fā)表于 2022-7-13 16:11
您是說(shuō)中斷自己不能恢復(fù)現(xiàn)場(chǎng),需要人為的PUSH,POP來(lái)恢復(fù)現(xiàn)場(chǎng)?而函數(shù)調(diào)用,C51的編譯器可以調(diào)用函數(shù)時(shí), ...

你是不是理解 混了?
你如果寫匯編的話, 是不用C51 編譯器, 用A51 編譯器的。
C51 的話, 函數(shù)是可以做成重入函數(shù)的, (即便他編譯報(bào)了有重入風(fēng)險(xiǎn))。
而 A51 的話,你只要用好了 PUSH POP 函數(shù)也可以做成  重入的。比如: 被調(diào)用函數(shù),用到 R0, 你只要函數(shù)入口 PUSH AR0, 出口 POP AR0  那么,這個(gè)函數(shù),你中斷調(diào)用了,一樣現(xiàn)場(chǎng)會(huì)被保護(hù)。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-14 08:26 | 顯示全部樓層
Y_G_G 發(fā)表于 2022-7-12 18:20
所謂"死機(jī)"和中斷無(wú)法跳出,這不過(guò)是推測(cè)而已,說(shuō)不定可能就是其它的小問(wèn)題而已
匯編是很容易出問(wèn)題的
如 ...

您好,這個(gè)可能不方便貼出,隨說(shuō)是20年的程序,但老板交代過(guò)。
經(jīng) 188610329大神提醒,我DPTR沒(méi)有保護(hù)造成的,但這個(gè)寄存器以前就沒(méi)有保護(hù),可能是我修改了程序,不保護(hù)不行了。匯編是很麻煩,要面面俱到。、z*cx您好,這個(gè)可能不方便貼出,隨說(shuō)是20年的程序,但老板交代過(guò)。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-14 08:39 | 顯示全部樓層
您好,是這樣,程序是匯編的,擴(kuò)展名是ASM,但是在KEIL C下編譯的,我注意到一個(gè)問(wèn)題,在KEIL C下新建一個(gè)匯編工程,它的擴(kuò)展名是A51,我懷疑這個(gè)程序最開始不是在KEIL C下編譯的,后來(lái)轉(zhuǎn)到KEIL C下,KEIL C內(nèi)部是不是有A51的編譯器?
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-14 08:45 | 顯示全部樓層
Y_G_G 發(fā)表于 2022-7-12 18:20
所謂"死機(jī)"和中斷無(wú)法跳出,這不過(guò)是推測(cè)而已,說(shuō)不定可能就是其它的小問(wèn)題而已
匯編是很容易出問(wèn)題的
如 ...

您好,剛才回復(fù)過(guò),提交時(shí)不小心按錯(cuò)了鍵,出現(xiàn)了亂碼,可能審核不通過(guò)。
這個(gè)程序,雖說(shuō)是20年前的了,但老板有交代,不方便貼出。
經(jīng)188610329 大神提醒,我懷疑是DPTR沒(méi)有保護(hù)造成的,我補(bǔ)充了一些代碼,可能是不保護(hù)不行了。
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-14 09:57 | 顯示全部樓層
datouyuan 發(fā)表于 2022-7-13 17:12
只有PC值能自動(dòng)恢復(fù),其它值得恢復(fù)要靠軟件操作。

剛才仿真了下,只看的R0,在中斷下,給它賦一個(gè)值,比如說(shuō)5,然后調(diào)用一個(gè)函數(shù),在函數(shù)中對(duì)R0修改為8,函數(shù)執(zhí)行完后,再返回調(diào)用它的那個(gè)中斷,發(fā)現(xiàn)R0的值還是8,看來(lái)在中斷中使用函數(shù)真不是一個(gè)好的習(xí)慣。
回復(fù)

使用道具 舉報(bào)

ID:883242 發(fā)表于 2022-7-14 19:44 | 顯示全部樓層
你的軟件用到了idata了嗎?
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-7-14 19:55 | 顯示全部樓層
newlined 發(fā)表于 2022-7-14 08:39
您好,是這樣,程序是匯編的,擴(kuò)展名是ASM,但是在KEIL C下編譯的,我注意到一個(gè)問(wèn)題,在KEIL C下新建一個(gè) ...

KEIL 就是編譯器,
KEIL C51 是在KEIL 下的 51單片機(jī) 用的C語(yǔ)言
KEIL A51 是在KEIL 下的 51單片機(jī) 用的A語(yǔ)言
你既然是 用的匯編,后綴還是 ASM 就肯定是用的 A51 編譯,怎么可能用 C51編譯?
兩者編譯方式完全不一樣, KEIL中的提示也不一樣,一個(gè)是: compiling xxxxxxx.C...  一個(gè)是:assembling xxxxxxx.ASM...
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-7-14 20:06 | 顯示全部樓層
newlined 發(fā)表于 2022-7-14 09:57
剛才仿真了下,只看的R0,在中斷下,給它賦一個(gè)值,比如說(shuō)5,然后調(diào)用一個(gè)函數(shù),在函數(shù)中對(duì)R0修改為8,函 ...

如果,你進(jìn)入中斷,用的是不同的寄存器組, 那么,你對(duì) R0 的操作,是不會(huì)影響 主程序的 R0的,因?yàn)椋?R0 不是 彼R0,  相對(duì)于這個(gè)問(wèn)題,我反而覺(jué)得,你應(yīng)該是 對(duì)某些寄存器的 現(xiàn)場(chǎng)保護(hù)沒(méi)有做好。你新加的內(nèi)容才是關(guān)鍵。
而且,你說(shuō)的部分內(nèi)容,我覺(jué)得非常困惑,“以前堆棧留的比較小,只有20個(gè)字節(jié),后來(lái)我又找了幾個(gè)加上了,但還是不大。” 你這個(gè)  只有20字節(jié)是什么來(lái)的? 又找了幾個(gè)加上 是怎么加的? 正常情況下, 一般分配完內(nèi)存地址后, 我們就在  內(nèi)存末尾 打上 Stack,作為堆棧的起點(diǎn),賦值給SP, 假定SP 為 80H, 那么 從80H 往后 到 0FFH 相當(dāng)于都是 堆棧用的。 所以不存在原來(lái) 堆棧只有多少,然后你還“找了幾個(gè)”的情況存在。 所以,你描述的這個(gè)情況,到底是什么情況?
回復(fù)

使用道具 舉報(bào)

ID:401564 發(fā)表于 2022-7-14 20:43 | 顯示全部樓層
newlined 發(fā)表于 2022-7-14 08:26
您好,這個(gè)可能不方便貼出,隨說(shuō)是20年的程序,但老板交代過(guò)。
經(jīng) 188610329大神提醒,我DPTR沒(méi)有保護(hù)造 ...

DPTR,R0,R1什么的,你在多個(gè)地方用到了,就進(jìn)行保護(hù),如果用不到就不用管
匯編子程序的原則是你在調(diào)用的時(shí)候,如果在其它地方你也用到某個(gè)地址的RAM.那就進(jìn)行保護(hù),每個(gè)子程序都要保護(hù)
常用的就是R0R1之類,比如DELAY:               
        PUSH R0        PUSH R1
        MOV R0,#100
        MOV R1,#100
NEXT:
        DJNZ R1,NEXT
        DJNZ R0,NEXT
        POP R1
        POP R0
        RET

這就是一個(gè)延時(shí)程序,這樣的話,你在其它的程序中包括中斷,再使用R0R1,也同樣的PUSH,POP,那么這個(gè)程序就不會(huì)出問(wèn)題
假設(shè)你整個(gè)完整的程序中,只有這一個(gè)地方用到R0R1,那么,這個(gè)PUSH,POP就是多余的
還有R0-R7這幾個(gè)地址,默認(rèn)的情況下,在整個(gè)程序地址是固定的,你在任何一個(gè)地方修改了R0-R7其中一個(gè)的值,它在其它地方的也是會(huì)改變的
假設(shè)你延時(shí)中用到了R0,中斷中也用到R0,那么當(dāng)延時(shí)程序被中斷打斷之后,如果不用PUSH,POP保護(hù)R0的話,等到中斷中修改了R0之后
RETI返回之后,R0的值就是中斷中最后操作的值,那么,你這個(gè)延時(shí)程序就出錯(cuò)了
你不要都是想著堆棧滿不滿的,基本不會(huì)的,完全可以先不管堆棧的大小問(wèn)題
專注找你自己代碼的問(wèn)題
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-7-14 21:07 | 顯示全部樓層
Y_G_G 發(fā)表于 2022-7-14 20:43
DPTR,R0,R1什么的,你在多個(gè)地方用到了,就進(jìn)行保護(hù),如果用不到就不用管
匯編子程序的原則是你在調(diào)用的時(shí) ...

R0~R7 屬于 通用寄存器, 是不能PUSH的。
如果是完全自己寫的代碼,配合USING 可以用 PUSH AR0~AR7 方式來(lái)PUSH 但是,如果不是自己的代碼,而4組寄存器 一直輪換在用的話,非常不好處理。
所以,還是比較建議樓主多注重一下,改了部分的代碼,到底涉及到哪些東西,針對(duì)性的處理一下,而不是去動(dòng)那些既存的,由來(lái)已久的代碼。
簡(jiǎn)易樓主,全程序  查找一下, "MOV  PSW,#"   看看具體用了幾組 通用寄存器,為了影響最小化,假定,之前只用了 3組寄存器,建議樓主加的部分代碼全都用 第四組 通用寄存器,這樣,可以把影響降到最低。
回復(fù)

使用道具 舉報(bào)

ID:883242 發(fā)表于 2022-7-14 21:41 | 顯示全部樓層
函數(shù)的好處是可以復(fù)用,一處定義多處調(diào)用,節(jié)約程序空間。

但是對(duì)于大多數(shù)8位單片機(jī)編譯器,包括C51,沒(méi)有按照標(biāo)準(zhǔn)c語(yǔ)言的做法——在進(jìn)入函數(shù)的時(shí)候在堆棧上臨時(shí)分配局部變量(具體做法可以看《數(shù)據(jù)結(jié)構(gòu)》關(guān)于遞歸的那一部分),因?yàn)?位機(jī)間接尋址指令和空間非常有限,按標(biāo)準(zhǔn)c語(yǔ)言的做法,最后生成的機(jī)器碼會(huì)非常龐大,占用的RAM空間也非常多,對(duì)本來(lái)就很少的資源造成巨大浪費(fèi)。

C51的做法是對(duì)函數(shù)調(diào)用關(guān)系進(jìn)行分析,然后靜態(tài)分配變量,以樓主的問(wèn)題為例A->A1->A2->A3,那么A的局部變量可能是27H~29H,A1的局部變量占用2AH~2FH,A2的局部變量占用30H~35H,A3的局部變量占用36H以后空間。這種做法導(dǎo)致中斷調(diào)用的函數(shù)是無(wú)法復(fù)用的!比如中斷B調(diào)用了函數(shù)B1,B1的局部變量占用33H這個(gè)空間,那么如果主程序調(diào)用B1,局部變量在運(yùn)算過(guò)程中發(fā)生了中斷,中斷B1修改了局部變量,那么中斷結(jié)束后,回到主程序,局部變量33H的內(nèi)容被修改了,那么主程序顯然就會(huì)執(zhí)行錯(cuò)誤。同樣的原因,不僅主程序不能調(diào)用B1,其他中斷C、D也不能調(diào)用B1!!!這個(gè)函數(shù)B1是中斷B專用的。

綜上所述,使用函數(shù),可以復(fù)用的優(yōu)點(diǎn)在中斷這里不存在!在中斷中調(diào)用函數(shù)只有各種各樣的缺點(diǎn),一點(diǎn)好處都沒(méi)有,樓主為什么要這么做?
回復(fù)

使用道具 舉報(bào)

ID:401564 發(fā)表于 2022-7-14 22:01 | 顯示全部樓層
188610329 發(fā)表于 2022-7-14 21:07
R0~R7 屬于 通用寄存器, 是不能PUSH的。
如果是完全自己寫的代碼,配合USING 可以用 PUSH AR0~AR7 方式 ...

好久不用匯編了,忘記了
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-15 10:58 | 顯示全部樓層
Hephaestus 發(fā)表于 2022-7-14 19:44
你的軟件用到了idata了嗎?

您好,用到了
回復(fù)

使用道具 舉報(bào)

ID:227818 發(fā)表于 2022-7-15 11:08 | 顯示全部樓層
Hephaestus 發(fā)表于 2022-7-14 21:41
函數(shù)的好處是可以復(fù)用,一處定義多處調(diào)用,節(jié)約程序空間。

但是對(duì)于大多數(shù)8位單片機(jī)編譯器,包括C51,沒(méi) ...

您好,在中斷中有十幾行語(yǔ)句,用了幾次,早先我不知道函數(shù)調(diào)用會(huì)產(chǎn)生一些列的問(wèn)題,就把它們寫成了函數(shù).前邊datouyuan大神也已經(jīng)指出了.
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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