2013年5月17日 星期五

簡單的 C 到底 compile 出什麼?


使用 AVRStudio 建立一個簡單的 C 語言程式,單純到只是將 Port B 的 bit #0 設定為輸出,並且將其輸出為 high 電位。程式原始內容如下:


經過 compile 所產出的 hex 檔案內容有一點長度,只是從組合語言的眼光來看,不知道到底為什麼出現一堆機械碼?


AVRStudio 除了可以用來發展程式,還可以將產出的 hex 檔案載入,轉譯成組合語言進行除錯。因此藉由 AVRStudio 開啟 hex 檔,來看看究竟那一小堆的機械碼到底用來幹啥?

如下就是這個 hex 檔載入後所轉譯的組合語言內容。

  • 重置起點從位址  0x0000 開始,第一行程式就是一個長距離的 RJMP 指令,跳到位址 0x0013 去;從位址 0x0001 到 0x0012 有一堆沒用到的中斷向量,其作用都是指到位址 0x0013
  •  真正的程式起點所做的第一件事是將狀態暫存器 SREG (0x3F) 清除;在這裡使用到一般暫存器 R1
  • 第二件工作是設定堆疊 SPH (0x3E)、SPL (0x3D) 暫存器。使用到一般暫存器 R28、R29,先將堆疊的值暫存在 R28、R29,再填入 SPH、SPL 中
  • 接著才是我們程式的真正內容:設定 DDRB 及 PORTB。從位址 0x001C ~  0x0021 是一組副程式,使用一般暫存器 R24 來存放值,再輸出到 DDRB、PORTB。這段副程式可以視為是 C 原始程式中的 main( )
  • 最後跳到位址 0x0023 的無窮迴圈
這裡有一個問題:在 C 的原始程式裡不是將主程式宣告為 int main(void)?程式的結尾不是 return 0?位址 0x001C ~ 0x0021 的副程式當中的後段將一般暫存器 R24、R25 設定為 0,莫非它就是那個 return 0?

如果把 main() 的傳回值宣告改成 void,compile 過程只會出現一個小警告訊息,還是可以順利產出 hex 檔案。
警告訊息:main( ) 傳回值應該是 int
看看 assembly 的轉譯,確實在使用者程式碼的部分少了關於 R24、R25 的設定。


再把程式改成某個特定傳回值,看看最後會 compile 出什麼?在這裡設定傳回值為 0x205,一個十六位元的傳回值:


果然在 R24 裡存放了 0x05,再 R25 中存放了 0x02,才會執行 RET 指令。


沒有留言:

張貼留言