2010-03-30

不可靠的 compiler

最近連續好幾個被 compiler 陷害的 bug ... 公司內有 MRC Code 用 Visual Studio 2003 的 VC++ compile 出來的東西,加一行減一行就看不到 bug 的問題; CPLD code 重新 compile 後 bug 就不見的問題,我自己做的玩具也被 8051 用的 SDCC 害到。公司的不便多說,先講講 SDCC 害人的情況。

主要是,程式寫好後用模擬器 (S51DEMO) 怎麼跑都OK,但一燒上 AT89S51 就不會動,hang 在 serial_init() 的位置。動用 /* 註解 */ 大法,終於找到問題出在一行 char str[] = {} 宣告:

__code unsigned char str[] = {
0x12, 0x33, 0xf0, 0x33, 0xf0, 0x12, // H
0x24, 0xf0, 0x24, // e
// ...
0x00 } ;

重點在 __code。如果不加的話,SDCC 會把它 compile 成 __DATA 很詭異地賦予初值,然後 AT89S51 就當在這了:

; kbd.c:168: unsigned char str[] = {
mov _main_str_1_1,#0x12
mov (_main_str_1_1 + 0x0001),#0x33
mov (_main_str_1_1 + 0x0002),#0xF0
mov (_main_str_1_1 + 0x0003),#0x33
mov (_main_str_1_1 + 0x0004),#0xF0
; ...
mov (_main_str_1_1 + 0x0024),#0x00
; 誰能告訴我為什麼 8051 執行過這邊就當掉 =.=

加了之後,就會是和其他字串常數一樣正常的 assembly code:

_main_str_1_1:
.db #0x12 ; 18
.db #0x33 ; 51
.db #0xF0 ; 240 ?
.db #0x33 ; 51
.db #0xF0 ; 240 ?
.db #0x12 ; 18
; ...
.db #0x00 ; 0