极品的C语言错误
?
?????今天在測試硬件通信模塊時(shí)候發(fā)現(xiàn)一個(gè)奇怪的問題,發(fā)送數(shù)據(jù)和接收數(shù)據(jù)進(jìn)行比較復(fù)制時(shí)候頻繁數(shù)據(jù)錯(cuò)誤。
數(shù)據(jù)收發(fā)抽象如下: uint16 i = 0; uint16 j = 0; uint32 error_num = 0; XX_send_data(i++); ? ? ?j = XX_rece_data(); ? ? if(i != (j + 1)) { error_num++; } 這段代碼按照理論上來說,只要發(fā)送數(shù)據(jù)i和接收數(shù)據(jù)一樣,那錯(cuò)誤計(jì)數(shù)器應(yīng)該不會(huì)出錯(cuò),但是實(shí)際上出錯(cuò)了,最開始懷疑是由于FPGA硬件模塊數(shù)據(jù)發(fā)送和接收時(shí)序有問題,但是多次大批量功能仿真以及時(shí)序仿真都沒問題。 這下我就開始懷疑這段短小的C程序是否工作正常,因此, 在error_num++這句話這里打斷點(diǎn),查看每次出錯(cuò)數(shù)據(jù)都是i=0,j=65535的時(shí)候出錯(cuò),為什么會(huì)全部出錯(cuò)在這里呢? 百思不得其解,后來詢問資深工程師飛哥,飛哥一看就看出問題出現(xiàn)在哪里了,讓我汗顏呀!!~~ 原來錯(cuò)誤是這樣發(fā)生的:(程序運(yùn)行在32位處理器) 這段程序從表面上看是沒有任何問題的,但是細(xì)致分析就會(huì)發(fā)現(xiàn),當(dāng)i=65535發(fā)送數(shù)據(jù),發(fā)送完成后執(zhí)行i++,i此時(shí)變?yōu)?,j調(diào)用接收函數(shù)后,返回值正確也是65535,但是,那看來問題就出現(xiàn)在if(i != (j+1))這里了。 原來,?j+1 這種算術(shù)運(yùn)算的運(yùn)算值是默認(rèn)存到32寄存器中,因此j+1運(yùn)算結(jié)果為32位數(shù)據(jù),因此,當(dāng)j=65535時(shí)候,(j+1)實(shí)則為65536,(0 != 65536),因此產(chǎn)生不匹配。錯(cuò)誤碼自加。 有很多種方法消除這種錯(cuò)誤,修改代碼如下即可解決問題。 uint16 i = 0; ? ? ?uint16 j = 0; ? ? ?uint32 error_num = 0; ? ? ? ?XX_send_data(i++); ? ? ?j = XX_rece_data(); ? ? ? ? ?if(i !=(uint16) (j + 1)) { ? ? ? ? ? error_num++; ?????} 終于找到問題了,看來以后寫代碼還得仔細(xì)了,吸取教訓(xùn)。 // 看了回復(fù),發(fā)現(xiàn)很多人都以純軟件的方式來理解這段代碼,但是嵌入式C語言里面一定要詳細(xì)和處理器行為結(jié)合起來,以下添加詳細(xì)解釋 這張截圖為這段代碼對應(yīng)的匯編代碼,詳細(xì)閱讀這段匯編代碼即可找出問題所在。 第一句匯編代碼ldhu r3,-10(fp) 意思為從內(nèi)存或者cache中加載一個(gè)半字,并且擴(kuò)展成無符號類型,這句話就是把變量i加載到寄存器R3中,R3為32位寄存器,這時(shí)候雖然變量i為uint16但是比較的時(shí)候還是變成了32位 第二句匯編代碼ldhu r2,-12(fp) 同上一句話一樣,這里是加載變量j到寄存器R2中 第三句匯編代碼addi r2,r2,1 /*問題所在*/? 這句話就是執(zhí)行的j+1,可見結(jié)果是保存在r2中,r2為32位寬的寄存器,所以當(dāng)i=0,j=65535時(shí),j+1 = 65536并未溢出,而是直接賦值給r2,此時(shí)r2即為65536,r3為0 最后一句匯編代碼 beq r3,r2,0x800258<main+92>這句話是比較r3和r2的值,如果相等就跳轉(zhuǎn)到0x800258<main+92>這個(gè)地址執(zhí)行程序。如果不相等就直接運(yùn)行下一句語句,也就是error_num++ 從上面的分析看出,嵌入式行業(yè)一定要對處理器非常熟悉,出現(xiàn)些稀奇古怪的問題,才能最終找到問題所在。
轉(zhuǎn)載于:https://www.cnblogs.com/linjie-swust/archive/2012/05/28/2522187.html
總結(jié)
- 上一篇: 正则表达式攻击
- 下一篇: 架构设计-业务逻辑层简述