問題與回答 -- 關於讀者 Mr.K 的第五封來信

On Thu, 20 Jan 2011 22:59:48 +0800, Mr.K wrote

再次打擾

請問
P5-5
5.2的標題"目的檔"
"目的檔"在我的認知裡是src code被編譯或組譯後產生的.o或.obj檔
那麼P5-3範例5.1 由於未使用到外部函式或變數 是否可以很單純的將產生的.o或.obj檔放到mem後就能執行?無須

loader似乎就可執行…如果這樣就可執行 那麼.o或.obj檔算是可執行檔嗎?

範例 5.1 的狀況非常的單純,這種格是的目的檔稱為映像檔。可以直接被載入記憶體執行,因此可以算是一種最

簡單的執行檔。

但是一般的目的檔格式並沒有這麼單純,通常有分程式段、資料段、BSS 段等,比較像圖 5.8 的樣子。


P5-32
5.7 目的檔格式 - a.out
a.out .com .exe .elf檔在我的認知裡是"可執行檔"
而書上5.7寫目的檔格式a.out,讓我有點困惑,目的檔和可執行檔的定義分別是什麼?
我認為對產生的.o或.obj檔案經過linking後能實際給CPU執行的才算"可執行檔"
另外請問像.bin,.img屬於可執行檔嗎?它們也需要專門的loader才可執行?

理論上,只要沒有外部變數的目的檔,就能被 Loader 載入執行,因此執行檔其實就是一種目的檔。

a.out 是 UNIX/Linux 中所使用的預設目的檔檔名,由於採用這個檔名,因此其格式也就被稱為 a.out,
.com .exe .elf, .bin, .img 都是執行檔的副檔名,.com, .exe 格式是 Windows 下的執行檔副檔名,在 Windows 底下的

.exe 格式是 PE/COFF 格式,.bin 也是執行檔的副檔名,.img 則是映像檔的副檔名 (也是一種執行檔),
在 Linux 下,目前使用的目的檔與執行檔格式都是 elf 的格式,其副檔名通常命名為 .o 或 .so。


P6-5
在C語言的設計中…那段
也可以利用inline指令?
請問inline是指令嗎?如以組語表示會是什麼?
那volatile也是指令嗎?如以組語表示會是什麼?
如果單純以C語言來說,我是覺得利用inline keyword比較正確

可以用 inline,但程式要改寫,如下所示:

檔案:inline.c

inline int max(a,b) {
  return (a>b?a:b);
}

inline int min(a,b) {
  return (a<b?a:b);
}

int main() {
  int x = max(3,5);
  int y = min(3,5);
  printf("max(3,5)=%d\n", x);
  printf("min(3,5)=%d\n", y);
}

執行 gcc -E inline.c -o inline.i 指令之後,就會得到 inline.i

檔案:inline.i

inline int max(a,b) {
  return (a>b?a:b);
}

inline int min(a,b) {
  return (a<b?a:b);
}

int main() {
  int x = max(3,5);
  int y = min(3,5);
  printf("max(3,5)=%d\n", x);
  printf("min(3,5)=%d\n", y);
}

volatile 並不算是指令,但也是一個關鍵字 (C99標準定義的),用來告訴 C 語言編譯器該變數是揮發性的,請編譯

器不要最佳化,這是用記憶體映射輸出入時使用的,詳細內容請看 11-5 ~ 11-13 頁,有描述記憶體映射輸出入的

用途與 volatile 的效果。

P7-9
圖7.8 (b)
第一行E= T ([+-] T)*是正確的嗎?

這是對的,但語法是我仿照 regular expression 所設計的 EBNF 語法, (…)* 代表出現 0 次以上。


P7-10
最下面 2.節點…<BASE>::=id|int…
int?是指迴圈內變數的型態嗎?還是多寫的?

<BASE>::=id|int… 當中的 :: 可以去掉,但這句話基本上是對的, id 是指變數名稱,int 是指整數數值,
舉例而言, x, y, i, person 等都是變數名稱,而 1, 35, 274, 3869 等都是 int。

如果是的話 也許可以是用type並指定只有整數類型(char,int…)

因為 C0 語言當中只有一種型態,就是整數 int,因此不用指定型態。

P7-20
圖7.17 說明了C語言的執行時記憶體配置
有程式開始時和程式執行中兩種分配情況
請問不同程式語言配置的方式不同嗎?

不同程式語言執行時的記憶體配置情況大致相同,但是也有例外,像是 PROLOG 的記憶體配置就有相當不同的

結構。


P8-3
圖8.2
編號2a和7a a的意思是?

a 的意思是該語句的 BNF 與 EBNF 不同,有就是有利用迴圈的方式消除左遞回,因此特別標示 a,但是由於我原

本有列出 BNF 版本,後來拿掉了,但是 a 還是被留下來了,這個 a 符號應該可以被去掉。

P8-4
第二行 第7條的BaseList=…
圖8.2第7條不是BaseList

抱歉,寫錯了,應該改為第 2 條的 BaseList 才對。

附錄A
A.5位元組順序
提到CPU0採用Big Endian
具我的認知實際擺入mem裡是用Big還是Little
要看編譯器 作業系統 CPU三者
而寫程式的人 需要注意什麼?
有什麼地方會影響到?

Big Endian/Little Endian 會影響到記憶體與磁碟中資料的儲存方式,寫程式若需要跨平台時就要特別小心,例如存入到檔案中傳給另一個平台讀取時就必須確認其一致性,否則數值就會錯亂。

從該書裡
像a:WORD 3會變成00000003這樣看來就是使用Big
假設有一筆32bits資料12345678(10進位) 放到位址100
高位元 低位元
0x100 12 34 56 78
byte0 1 2 3
offset 0x0 1 2 3
LDB R1,[100]
不是應該載入位址100上的值(12)
為什麼書上是取byte3?
byte3應該在0x103上才對?
我的觀念是依據資料原本的MSB和LSB來排 應該是byte3~0
這樣byte3就是在0x100上

如果是我的觀念錯了
那麼請問
如果是Little是下面這樣嗎?

高位元 低位元
0x100 78 56 34 12
byte3 2 1 0
offset 0x0 1 2 3

書上 (A-6 頁) 所謂存取 byte3 的意思是當我們宣告如下的程式時

a: BYTE 0x12

LDB R1, a

LDB R1, a 會將 0x12 載入到暫存器 R1 的 byte 3 當中,也就是 R1 中代表數值較小的那一個 byte。

有關 Endian 問題可進一步參考網路文章 Big Endian和Little Endian的比較(2010/4/26更新)

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License