Re: [問題] 變數問題

看板ASM (組合語言)作者 (ksmrt)時間15年前 (2010/01/16 01:00), 編輯推噓3(301)
留言4則, 4人參與, 最新討論串3/3 (看更多)
因為應該會有其它人可能會碰到類似問題, 就直接回版上了, 這樣討論也比較方便. 簡單重覆你遇到的問題. main() 中有段code : test = 0; : while(test<0x0130) {...} 而在isr()中會做 : ++test; 除此之外並無其它對test之讀寫. 遇到的問題是 while 迴圈"偶而"會在非預期的時候 (test的值明明還小於0x0130時)就跳出來. ※ 引述《ksmrt0123 (ksmrt)》之銘言: : 下面有我disasemble的結果. : test 是定義成unsigned int, 放在 data 0x08(MSB) 跟 0x09(LSB). : 可看出 test<0x0130要由好幾個組合語言指令來完成. : 你可想看看當test<0x0130做到一半, : 若發生 RI interrupt, : 是否有什麼狀況會造成你遇到的錯誤? : 18: while(test<0x0130) { : C:0x0012 C3 CLR C : C:0x0013 E509 MOV A,0x09 : C:0x0015 9430 SUBB A,#0x30 : C:0x0017 E508 MOV A,test(0x08) : C:0x0019 9401 SUBB A,#0x01 : C:0x001B 500A JNC C:0027 從反組譯的程式可看出, test是兩個byte的變數, MSB放0x08, LSB放在0x09. 判斷 test<0x0130 是由 0x0015跟0x0019兩個SUBB組成, 經過這兩個SUBB若 C==0, 表示test<0x0130不成立, 就跳出迴圈(0x001B JNC ...). 會發生錯誤的情況是, 當test==0x00ff時, main()執行 上面那段code 執行到一半時 (0x0015的SUBB已執行完, 但0x0019的尚未執行), 發生interrupt, isr()因此會做 ++test, 故isr() 結束後 test的值是 0x0100. 51現在又回到main()繼續剛才未完成的工作. 執行到0x0019那個SUBB, 此時test的MSB的值已是0x01, 前一個SUBB(0xFF-0x30)也不會設定C, 所以運算結果C會是0, 就跳出迴圈了. 這就是你遇到的狀況. 這個問題最簡單的解決方法就是在計算 test<0x0130 時暫時 disable interrupt, 這樣 isr()就不會來插一腳造成錯誤. 但要disable interrupt以這段C code來說, 因為 test<0x0130 是embedded在while loop中, 所以從C直接加不太好加... 另有個相關的問題, main()中的 test = 0; 把test的值寫為0 需要分成至少兩個指令做, 那會不會有類似的狀況造成錯誤呢? -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 219.68.71.218 ※ 編輯: ksmrt0123 來自: 219.68.71.218 (01/16 01:14) ※ 編輯: ksmrt0123 來自: 219.68.71.218 (01/16 11:50)

01/18 10:51, , 1F
分析的真詳細...
01/18 10:51, 1F

01/18 13:45, , 2F
同上...
01/18 13:45, 2F

01/18 19:34, , 3F
Good!!
01/18 19:34, 3F

01/21 21:11, , 4F
改用16bits MCU就好了 .......來亂的XD
01/21 21:11, 4F
文章代碼(AID): #1BK9z5v9 (ASM)
討論串 (同標題文章)
文章代碼(AID): #1BK9z5v9 (ASM)