C51的首次出現
對於熟悉組合語言的工程師,第一次寫C51的程式,心中其實是有些不安的。比如組合語言有虛擬指令,像是 .ORG,可以用來告訴編譯器,程式碼要放在位址0,C語言沒有類似的虛擬指令,程式碼要放在何處,就是由C51編譯器決定。
#include "at89x52.h"
__sfr __at (0x91) P1M1;
__sfr __at (0x92) P1M0;
//*********************************************************
// delay program
//*********************************************************
void DelaySub(void)
{
unsigned int i;
for (i=0; i<0xFFFF; i++) {}
}
//*********************************************************
// main program
//*********************************************************
void main(void)
{
P1M1=0; P1M0=0xFF; /* P1 set as Output */
while (1) { P1_0=1; DelaySub(); P1_0=0; DelaySub(); }
}
C51的編譯動作
將專案4C-LED Flash 編譯後,發現目錄中多了一個main.lst的檔案,這個檔案的部分內容是這個樣子:對照C原始程式,可以發現C51編譯器,其實是將main.c原始碼,先翻成組合語言原始檔,真正進入編譯程序的,還是組合語言程式碼,這正好也呼應了作者的說法,要學組合語言,但不要寫組合語言程式,因為C51編譯程式已經將組合語言程式碼編好了。某種程度上,組合語言是C51自動化生產的結果。
370 ; function DelaySub
371 ; -----------------------------------------
000000 372 _DelaySub:
000007 373 ar7 = 0x07
000006 374 ar6 = 0x06
000005 375 ar5 = 0x05
000004 376 ar4 = 0x04
000003 377 ar3 = 0x03
000002 378 ar2 = 0x02
000001 379 ar1 = 0x01
000000 380 ar0 = 0x00
381 ; main.c:13: for (i=0; i<0xFFFF; i++) {}
000000 7E FF [12] 382 mov r6,#0xFF
000002 7F FF [12] 383 mov r7,#0xFF
000004 384 00104$:
000004 1E [12] 385 dec r6
000005 BE FF 01 [24] 386 cjne r6,#0xFF,00112$
000008 1F [12] 387 dec r7
000009 388 00112$:
000009 EE [12] 389 mov a,r6
00000A 4F [12] 390 orl a,r7
00000B 70 F7 [24] 391 jnz 00104$
00000D 22 [24] 392 ret
雖然C51可以正確的編譯出下以下載執行的HEX檔案,但有兩個因素還是讓作者不安,第一:堆壘編譯器會設定嗎?堆壘沒有設定,函式的呼叫就會有問題。第二:下載的機器碼會放在位址0的位置嗎?如果沒有,程式的執行一樣會出問題。
這個程式下載執行後,LED開始閃動起來,顯然C51的作者早知道作者心中的疑問,這些因素早就考慮清楚了。