MCS 51 A51 程式跑飛怪相

2021-06-07 06:01:12 字數 2308 閱讀 2803

程式跑飛怪相

1.跑飛的程式

昨天凌晨寫了個程式,太晚就睡了。昨天早晨9點多鐘的時候,除錯程式居然發現程式跑飛了。

跑飛程式部分**如下:

tleft:	mov		1000h,#006h ;迴圈次數

mov a,1001h

push acc

lloop: setb p1.2

pop acc

mov p0,a

clr p1.2

rr a

push acc

acall delay

dec 1000h

mov a,1000h

jnz lloop

ret

本段**是某個程式中的乙個子程式,子程式主體執行結束時,再執行子程式返回指令(ret)。這時奇怪的跳到了0xfc00位置的空操作。

2.問題分析

子程式返回跳轉的位址為「0xfc00」,即可以得出是出棧的問題。

不過我剛開始遇到該問題的時候,不是這麼認為的。問題歸咎於堆疊溢位,於是昨天下午查詢了好多資料並綜合了網友的一些方法來進行**測試。其中乙個網友要求我把acall和ret全部換成ljmp指令,這樣處理後雖然能夠順利執行,但是達不到彙編模組化程式設計的目的。其後又查詢了一些資料,都沒有派上用場。

昨天晚上沒開電腦,好好的休息了一晚上。今天早晨開啟程式,用軟體**除錯時,發現sp長度的變化。於是重新進入**,一步步除錯,並把每次呼叫acall指令的sp長度值記錄下來。直到子程式主體部分執行結束,然後執行子程式返回指令(ret),發現sp長度比在執行「acall tleft」時的sp長度多了乙個。後來仔細想想,其實是在子程式中對累加器a壓棧了,但是子程式返回之前沒有出棧。

3.解決方案

解決方案就是簡單的一句話,在子程式返回指令(ret)之前加一條出棧語句就ok。

修改後的**如下:

tleft:	mov		1000h,#006h ;迴圈次數

mov a,1001h

push acc

lloop: setb p1.2

pop acc

mov p0,a

clr p1.2

rr a

push acc

acall delay

dec 1000h

mov a,1000h

jnz lloop

pop acc

ret

4.深度分析

其實根據上面的sp長度的判斷,是可以判斷出程式的返回問題致使程式跑飛。

但是考慮問題時,需要從多方面著手,綜合分析程式的問題所在。

為什麼程式會跑飛到「0xfc00」,而不是其他的地方呢?

「0xfc00」可以分解成fc和00,那麼fc是怎麼來的呢?不妨我們仔細看看剛才那段跑飛的程式。一步步**除錯後發現,到子程式主體部分執行結束時,累加器a的值正好是0xfc。這兩者之間就有著莫大的關係,因為程式中有對累加器a的壓棧操作。因此,需要再子程式返回(ret)之前對累加器a出棧。

對「0xfc00」的分解判斷,也可以從「acall tleft」呼叫tleft子程式時對堆疊的處理進行分析。

acall指令詳解:

(pc)←(pc)+ 2

(sp)←(sp)+ 1,(sp)←(pc7-0)

(sp)←(sp)+ 1,(sp)←(pc15-8)

(pc10-0)←addr11

ret指令詳解:

(pc15-8)←(sp),(sp)←(sp)-1

(pc7-0)←(sp),(sp)←(sp)-1

由上面兩條指令詳解,可以看出「acall tleft」下一條指令的高位位址為00。假設「acall tleft」這條指令的位址為0x0012,那麼「acall tleft」下一條指令的低位位址為14。即「acall tleft」下一條指令的位址為0x0014。

跑飛程式主體部分執行結束時,堆疊圖如下圖。

修改後程式主體部分執行結束是,堆疊圖如下圖。

5.心得體會

剛開始的時候,我根本就沒有深入「0xfc00」這個問題。如果直接從這個問題著手的話,或許昨天上午就能把問題解決。可惜是我沒有那樣做。不過現在想來,知識經驗的積累就是從錯誤的點點滴滴開始的。

今天的積累,鑄就明日輝煌。故留此一筆。

MCS 51 延時程式

該 為keil實際除錯分析後所得出結論,因計時仍為粗略計時,故採用軟體定時時應當採用毫秒級定時並且輸入變數x值不應過大,防止出現較大誤差 12mhz stc y1指令集 void delay1ms uint x 該函式宣告佔4個機器週期 12mhz stc y1指令集 void delay1ms u...

MCS 51硬體結構

具有cpu,ram,rom,定時 計數器以及io口等基本功能 按功能可分為三類 資料匯流排,位址匯流排和控制匯流排.aluacc 執行加減運算 b執行乘除運算.乘法 乘數取自a和b,結果a存低位元組,b存高位元組 除法 a存被除數,b存除數 結果商存a,餘數存b 暫存器暫存進入運算器前的資料 pcs...

MCS 51微控制器基礎

1.data,idata,xdata,pdata 的區別 data 固定指前面0x00 0x7f的128個ram,可以用acc直接讀寫,速度最快,生成的 也最小。idata 固定指前面0x00 0xff的256個ram,其中前128和data的128完全相同,只是訪問方式不同。i用類似c中的指標方式...