2013年4月13日 星期六

指標 (Point)

https://4rdp.blogspot.com/2013/04/point.html?m=0

今年初看了探奇自然科學教室邱老師的貼文 http://touchclassroom.blogspot.tw/2013/04/point.html,說到 ROBOT C 開始提供 Points,真是好消息,因曾承諾邱老師撰文留個心得記錄,今天發表貼文。

C語言和組合語言(Assembly)具有很深的血緣關係,C語言之所以被設計出來,是為了方便韌體工程師開發程式免於被組合語言摧殘,記起二十多年前學生時代,自己獨力撰寫一個 2 kB MOS 6502 (APPLE II 時代) 的程式,雖然只花一周的時間寫出來,但是偵錯卻用三倍的時間除蟲!事後還誇下豪語,說以後再也不碰組合語言這種東西!!不過從事韌體工程師的人哪有不接觸的?還好有 C語言解救了我們,而指標正是C語言的特色之一。

回歸正傳,在談指標之前需要認識一點 CPU 也就是組合語言的軀體,各種 CPU 都有提供間接定址的功能,指標的設計就是利用 CPU 這個功能,就以 Intel 8051 舉個例子:


MOV A,#data
把數值data複製到暫存器A
寫高階程式語言的人都知道,它相當於 A = 3

MOV A,address
把某記憶位址內的資料複製到暫存器A
相當於高階程式語言 A = B

MOV R,#address
把數值address複製到暫存器R
相當於C語言 R = &B

MOV A,@R
以暫存器Rn的內容當做位址,將該記憶位址內的資料複製到暫存器A
相當於C語言 A = *R

以上述指令為例,如果想把數值3複製到暫存器A,可以直接用第一個指令設定它。也可以用第二個指令方法,將記憶體位址B的內容複製到暫存器A,不過前提是記憶體位址B裡面的內容為3,也就是 B = 3,如果B是其它數值,那麼暫存器A的內容會依據複製記憶位址B當時的數值而定,指令三與四是一組的,先指定記憶體位址B到暫存器R,然後以暫存器R內的地址資料,複製到暫存器A。

或許用更淺顯的概念比較容易理解,假想CPU是一個搬運工,第一個指令相當於搬一張桌子到A家,第二個指令等於直接從住家B搬東西到A家,B家有甚麼東西,搬運工就搬甚麼東西,第三條指令則是提供搬運公司R,B住家的地址,然後第四條指令為搬運公司R依地址搬東西到A家。

關於指標用法,在Xander部落格文章中解釋得很清楚,在此不再贅述,不過指標在程式中有甚麼用途?以個人經驗,最常利用它當作資料查表索引,雖然陣列可以將資料排列儲存,但是只能限定一種固定長度資料形態,如果想儲存的資料是變動長度的,那使用指標最恰當不過,舉例來說字元陣列,
char A[3][6]={
"POINTS",
"CAT",
"BOOK"
}
這字串陣列宣告必須以最長字串來宣告,較短的字串會以零值補充尾部,如果想儲存多於六個字元的字串,那陣列就會覆寫到下一筆資料,因為C語言程式編譯時,不會幫你檢查索引範圍,等程式執行後,才會察覺有錯誤。 如果採用指標,資料可以存成
{0x06,"POINTS",0x03,"CAT",0x04,"BOOK"},以最節省記憶體空間方式儲存,然後以指標當索引指示。

另外想引用其它程式的資料,也非得使用指標,這就是為什麼Windows API多以指標當參數,提供使用者程式呼叫引用,因為Windows程式執行沒有固定記憶體位置,只有利用指標的特性,才能跨界引用以及隨需求更改。

那NXT程式可以如何利用?我覺得NXT有指標最大的優點可突破字串長度限制,ROBOT C限制字串長度最大20個字元,改以字元指標就可以超過長度限制,原則上記憶體空間有多少,就可以引用多少。




2 則留言:

  1. 8051,大學時代專題曾用過,已經太久沒接觸了。
    Bridan還能記得這些指令真是太厲害了!!

    至於指標應用,粗略記得是在高階語言比較有出現,例如C,但我對指標應用不甚熟悉,最廣泛應用還是停留在矩陣、陣列的座標索引操作。

    研究所寫程式控制倒立單擺、機械手臂等,也都是用C控制。坦白說還是沒實際把指標好好發揮。也許,只求功能正確就好。^___^

    回覆刪除
    回覆
    1. 薛老師客氣了,

      每種程式指令有其功用,不是每種場合都要引用炫耀,指標程式不容易閱讀及構思,我也是必要時機才用它。

      8051 不是我熟悉的 CPU,指令是從網路上查詢來的,因為許多人用就以它舉例比較親民。

      刪除