# 2018q3 Homework1 contributed by < `Winnie1230` > ## [現代處理器設計](http://hackfoldr.org/cpu/) ### Instruction Execution in 5-stage pipeline ![](https://i.imgur.com/LLlVkQ0.gif) >中英文字請空白隔開 >[name=課程助教][color=red] 目的是為了讓CPU在每個時間都有事情可以做 1. **IF** : Instruction Fetch 提取指令 - **PC**(Program Counter; ARM) or **IP**(Instruction Pointer; Intel) - PC決定接下來要執行的指令,也就是說只要改變PC即可改變程式執行的流程 :::info ARM的PC會指向下兩道指令 ::: 2. **ID** : Instuction Decode - 處理的不是instruction而是microOP 3. **EX** : Execution - microOP - 如何提升microOP執行的平行度?如何有效調度microOP? :::warning :question: 要如何執行?要如何有效的執行? ::: 4. **MEM** : memory 5. **WB** : Write Back :::info [AMD](https://zh.wikipedia.org/zh-tw/%E8%B6%85%E5%A8%81%E5%8D%8A%E5%AF%BC%E4%BD%93) 與 [Intel](https://zh.wikipedia.org/wiki/%E8%8B%B1%E7%89%B9%E5%B0%94) 在指令集部份會交叉授權 ::: ### Microarchitecture ![](https://i.imgur.com/fimRkAB.jpg =300x) ## [Bit-wise operations](https://hackmd.io/s/By0MltO_m) ### Bit-wise operators 1. **<<** : shift left , **>>** : shift right ```C 5 << 1 = 10 //00000101整個往左移動1個bit 5 << 2 = 20 5 >> 1 = 2 5 >> 2 = 1 ``` :::info 向左移動一個bit,整個數值會是原本的兩倍 向右移動一個bit,整個數值會是原本的1/2倍 ::: :::warning 「整個數值會是原本的 ? 倍」的陳述不精準,因為可能會遇到 shift 導致某些 bit(s) 被捨棄,自然新數值就不是倍數關係 :notes: jserv ::: >謝謝老師 :smile: > [name=劉育如] 2. **|** : bit-wise OR 3. **^** : bit-wise XOR 4. **~** : bit-wise NOT ### operations 1. Set a bit(僅設定一個位元) ```C unsigned char a |= (1 << n); ``` 2. Clear a bit ```C unsigned char b &= ~(1 << n); ``` 3. Toggle a bit(轉換指定位置的位元) ```C unsigned char c ^= (1 << n); ``` 4. Right/Left most bytes assuming 16 bit, 2-byte short integer: ```C unsigned char right = val & 0xff; /* right most (least significant) byte */ unsigned char left = (val >> 8) & 0xff; /* left most (most significant) byte */ ``` :::info 0xff = 0000000011111111 , 0xff的意思是只去後面8個bits 0x3039(即Hex)=12345 (Dec) ::: 5. sign bit assuming 16 bit, 2-byte short integer, two’s complement: ```C bool sign = val & 0x8000; // sign bit ``` :::info 表示有號數(signed numbers)時,第一位若是1則表示此數為負數,若是0則表示此數為正數 ::: #### 參考資料 [程式札記](http://puremonkey2010.blogspot.com/2011/05/c-bitwise-operation.html) ## [「你所不知道的C語言」系列講座](https://hackmd.io/s/HJpiYaZfl) ### 開發工具與規格標準 :::info C語言最早是用來開發Unix系統 ::: #### 為什麼不探討C++? 1. C++所涵蓋的範圍太廣,內建太多機制 - 上個世紀的C++ 被稱為「物件導向的程式語言」,這個世紀探討的C++ 應該稱為Metalanguage比較恰當,其包含[Object Oriented Programming](https://zh.wikipedia.org/wiki/%E5%85%83%E8%AA%9E%E8%A8%80)及[Genertic Programming](https://zh.wikipedia.org/zh-tw/%E6%B3%9B%E5%9E%8B) - STL(generic programming) 2. 發展及擴張速度太快 - 從C++ 14到C++ 17增加了Parallelism TS, Networking TS...等等 3. 要面對編譯器不相容的問題 - 現釋出最新的GCC是GCC8.2(release 2018/07/19) :::info GCC 7.1是個具備工業強度的編譯器,**重要的特徵是支援C++ 17** ::: :::success **glibc(grub libc)** - 常用的C語言的程式庫 - 授權條款是LGPL(當你在撰寫程式時,僅把libc當作「動態連結的函式庫」且應用程式內容並沒有參照到GPL的source code的話,授權條款是相對比較寬鬆的) [稍稍鬆綁的堅持-LGPL](https://www.openfoundry.org/tw/legal-column-list/519--lgpl) **musl libc** - 另一個C語言的程式庫 - 授權條款是MIT License(只要**不要把作者的名字塗掉**,不論以binary code的形式輸出或是以source code的形式輸出都可以) - 本質上與glibc是相同的 其他的授權條款: [BSD License](https://zh.wikipedia.org/wiki/BSD%E8%AE%B8%E5%8F%AF%E8%AF%81) ::: :::info C語言本質上是高階語言,但卻具備很多低階語言的特性 e.g. 毀滅者戰士的開發者 John Carmack 表示:c語言是一個wysiwyg(what you see is what you get)的語言(因為c語言程式碼對應到的組合語言、二進位,基本上都符合預期) ::: :::info Linux Kernel是一個高度物件導向開發的專案,堅持用c語言開發 ::: #### 延伸閱讀 - 第一個 C 語言編譯器是怎樣編寫的? :::success [compiler bootstrapping](https://en.wikipedia.org/wiki/Bootstrapping_(compilers)) ::: ### ISO/IEC 9899 (簡稱 “C99”) c++ 一開始只是class extensions to c language,一直到c99(c語言在1999年規範),c語言與c++開始分道揚鑣 :::warning In C, everything is representation!!! 在C語言中,所有東西都是一個「明確的空間」。之所以會有**型態**,是因為可以去宣告它資料的大小 ::: #### ISO與IEC - ISO(International Organization for Standardization,國際標準化組織) - IEC(International Electrotechnical Commission,國際電工委員會) - 這兩個單位常常會一起合作推出新的標準 e.g. C語言的標準即ISO/IEC 9899 e.g. [ISO/IEC 646](https://en.wikipedia.org/wiki/ISO/IEC_646)是與鍵盤輸入有關的標準 :::info ==e.g.== 是拉丁文 exempli gratia 的縮寫,意思是「舉個例子,比如」,等同與 "for example" ex- 是「前」的意思,不要用錯 :notes: jserv ::: #### [規格書](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf) 1. C99是在1999年定案的規格稱為C99,但是C99本身會有微調 2. 規格書可以澄清很多誤解 e.g. &可能是AND, bit-wise AND, 用於指標操作時則稱為「address-of operator」 e.g. * 可能是multiplication,用於指標操作時則稱為「indirection operator」或「value-of operator」 e.g. [ ] 稱為「array subscripting operator」 * 可參考[Operators in C and C++](https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B) :::info 事實上,C語言沒有真正的array,它最終都會轉換成**同等功能的指標** ::: 3. C++ 與C語言對**lvalue**的解釋意思不相同,lvalue在C99中的解釋 **l** 並不代表「left」,而是表示「locate」 4. 以下程式碼: ```C int main() { char *ptr; char str[] = "Hello World"; ptr = str; } ``` 在 **ptr = str**這一行,必須先了解: (在64bits下) | | ptr | str | | ------- | ------- | --- | | 資料型態 | char* | char[ ] | |sizeof()代表的意義|指標本身的大小|strlen(str)| |sizeof()|sizeof(ptr)=8bytes|strlen(str)=11| :::warning 既然儲存空間不同,自然就不會相同!!! 規格書就是來釐清這樣誤解 ::: :::info "Hello World"這種宣告方式是**string literal** 而字串後有一個**null terminator(空字符)** strlen(string)所計算的字串長度並**不包含**空字符,但是真正的儲存空間是有包含空字符的,也就是說sizeof(string)所得到的結果是有包含空字符的!!! ```C #include<stdio.h> #include<string.h> int main(){ char s[]="Hello World"; printf("%d %d\n",strlen(s),sizeof(s)); } ``` 執行結果: ```C 11 12 ``` ::: 5. sizeof() 不是一個function而是一個**operator**(規格書6.5.3.4) 6. 以下程式碼: (1) ```C #include<stdio.h> struct A{ int x,y; }; int main(){ struct A a; //建立一個struct A的物件a printf("%d %d\n",sizeof(struct A),sizeof(&a)); //&a指pointer的大小 } ``` 執行結果: ```C 8 8 ``` :::warning :question: 不太了解sizeof(&a)為什麼是指pointer的大小? 如果把上述程式碼寫成: ```C #include<stdio.h> struct A{ int x,y; }; int main(){ struct A *a; //建立一個struct A的指標a printf("%d %d\n",sizeof(struct A),sizeof(a)); ``` 指的是相同的意思嗎?還有sizeof(&a)跟sizeof(a)的差異在哪裡呀? ::: (2) ```C #include<stdio.h> struct A{ int x,y; }; struct B; //no definition=>forward declaration int main(){ struct A a; struct B *b; printf("%d %d\n",sizeof(struct A),sizeof(struct B)); } ``` 執行結果: ```C invalid application of ‘sizeof’ to incomplete type ‘struct B’ printf("%d %d\n",sizeof(struct A),sizeof(struct B)); ``` :::info sizeof operator 遇到incomplete type ::: 7. **wchar** 在IEC61131中有規範 8. C99具有**designated initializer**,但C++ 是不支援的,因為C++有constructor :::success **designated initializer** - 讓struct , array , union初始化變得更方便 - array 初始化: ```C int a[10] = {[1]= 1, [8 ... 9]=10}; //僅初始化a[1],a[8],a[9],其餘數值等於0 ``` 上述程式碼相當於: ```C int a[10] = {0, 1, 0, 0, 0, 0, 0, 0, 10, 10}; ``` - struct初始化(也可用於union) ```C struct point { int x; int y; }; struct point p = { .y = 1, .x = 10 }; ``` 上述程式碼相當於: ```C struct point p = { 10, 1 }; ``` - [index]和 .fieldname稱為**designator** - 使用這個特性就可以按照**任意順序**初始化array,struct和union中的成員 ::: 9. 沒有「雙重指標」,只有「**指標的指標**」 在C語言中,沒有什麼double pointer,只有pointer to...(e.g. 指標的指標:pointer to pointer) ### 函式呼叫篇 1. [History of C](https://en.cppreference.com/w/c/language/history) - C語言還是一個持續在改變的語言 - 從C11開始加入了很多現代處理器的特徵(尤其專注在concurrency、新的浮點數的支援、執行序與作業系統界面的釐清) - C17之後又更專注在平行程式設計的部份