實驗原理與內容
本實驗每位學生拿到一個datalab-handout.tar文件。學生可以通過U盤、網盤、虛擬機共享文件等方式將其導入到Unbuntu實驗環境中,選擇合適位置存放。然后在Ubuntu環境下解壓。解壓后,根據文件中的敘述和要求更改bits.c文件。本次實驗的主要操作方式為:使用C語言的位操作符實現題目要求。
需要完成bits.c中下列函數功能,具體分為三大類:位操作、補碼運算和浮點數操作。
1.位操作
表1列出了bits.c中一組操作和測試位組的函數。其中,“級別”欄指出各函數的難度等級(對應于該函數的實驗分值),“功能”欄給出函數應實現的輸出(即功能),“約束條件”欄指出你的函數實現必須滿足的編碼規則(具體請查看bits.c中相應函數注釋),“最多操作符數量”指出你的函數實現中允許使用的操作符的最大數量。
也可參考tests.c中對應的測試函數來了解所需實現的功能,但是注意這些測試函數并不滿足目標函數必須遵循的編碼約束條件,只能用做關于目標函數正確行為的參考。
表1 位操作題目列表
本題分數 | 函數名 | 功能 | 約束條件 | 最多操作符數 |
1 | isZero | 判斷變量x是否為0。如果為0,則返回1;否則,返回0。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ << ?>> | 2 |
1 | specialBits | 構建0xffca3fff,并返回。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ << ?>> | 3 |
1 | upperBits | 根據輸入的變量n,構建一個高n位為1其他位為0的數,并返回該值。 注:0<= n?<=32 | 僅可以使用以下操作符:?! ?~ ?& ?^ ?| ?+ << ?>> | 10 |
1 | bitMatch | 構建一個比特序列(int型),構成規則如下:如果x和y在某一個bit位置的值相同,則此序列的相應位置為1,否則該位置值為0。 | 僅可以使用以下操作符: ~?& | 14 |
1 | bitOr | 計算按比特或(x?|?y),并將計算結果返回。 | 僅可以使用以下操作符: ~?& | 8 |
4 | logicalNeg | 使用位操作符實現邏輯非(!x)操作,并將取邏輯非之后的結果返回。 | 僅可以使用以下操作符:?~ ?& ?^ ?| ?+ ?<< ?>> | 12 |
4 | bitParity | 如果x中包含奇數個0,則返回1;否則返回0。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 20 |
2 | byteSwap | 將x的第n字節和第m字節交換, 0?<= n <= 3,? 0?<= m <= 3, 然后將交換后的值返回。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 25 |
2 | getByte | 提取x的第n個字節。0 <= n?<= 3?(0代表最最低為字節,3代表最高位字節),并將其返回。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 6 |
2 | oddBits | 返回一個32bit數,這數的所有第奇數個bit位置的值為1。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 8 |
3 | replaceByte | 將x的第n個字節用 c?進行替換, 0 <= n <= 3,?0 <= c <= 255 并將替換后的結果返回。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 10 |
3 | rotateLeft | 將x向左循環移位n個bit。循環移位是指左邊移除去的比特自動填充到右邊空出的位置上。 0 <= n <= 31,并將循環移位后的值返回。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 25 |
2.補碼運算
表2列出了bits.c中一組使用整數的補碼表示的函數。可參考bits.c中注釋說明和tests.c中對應的測試函數了解其更多具體信息。
表2 補碼運算題目列表
本題分數 | 函數名 | 功能 | 約束條件 | 最多操作符數 |
2 | negate | 將輸入參數x的值取相反數,返回-x。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 5 |
4 | absVal | 計算變量x的絕對值,并將其絕對值返回。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 10 |
3 | isGreater | 如果x?>?y,則返回1,否則返回0。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 24 |
2 | isNegative | 如果x?< 0,返回1;否則返回0。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 6 |
4 | isPower2 | 如果x是2的整數次冪,則返回1;否則返回0。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 20 |
3 | addOK | 如果x+y沒有溢出,則返回1;否則返回0。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 20 |
3 | subtractionOK | 如果x-y沒有溢出,則返回1;否則返回0。 | 僅可以使用以下操作符: ! ?~ ?& ?^ ?| ?+ ?<< ?>> | 20 |
3.浮點數操作
表3列出了bits.c中一組浮點數二進制表示的操作函數。可參考bits.c中注釋說明和tests.c中對應的測試函數了解其更多具體信息。注意輸入參數和返回結果均為unsigned int類型,但應作為單精度浮點數解釋其32 bit二進制表示對應的值。
表3 浮點數操作題目列表
本題分數 | 函數名 | 功能 | 約束條件 | 最多操作符數 |
2 | floatAbsVal | 通過bit級操作返回一個float型浮點數的絕對值。如果輸入參數為NaN,則直接返回輸入參數的原值。 | 可以使用任何的操作符,包括||和&&。也可以使用if,while。 | 10 |
2 | floatIsEqual | 判斷兩個浮點數是否相等,如果相等則返回1,否則返回0。 如果輸入參數中含有NaN,則返回0。 注:+0和-0被當作相等的情況對待。 | 可以使用任何的操作符,包括||和&&。也可以使用if,while。 | 25 |
實驗過程與結果(可貼圖)
安裝gcc和ubuntu
isZero函數
isZero函數可能會接受一個數字作為輸入,然后返回一個布爾值,該布爾值表示該數字是否為零。如果是零,函數返回True;如果不是零,函數返回False。
Negate函數
這個函數將接受一個數值作為輸入,并返回其相反數。如果輸入是正數1,則返回-1;如果輸入是負數-1,則返回1;如果輸入是零0,則返回0。
specialBits函數
這個函數目前學的還不是很懂,去一個地址再返回一個新的地址。
upperBits函數
這個函數檢查函數為零的位,不為零跳到下一位,直到所有位為非零為止。
bitMatch函數
這個函數會返回一個x與y相等的位,用&操作符能恰好解決。
bitOr函數
這個函數會返回一個x與y相或的數,先對兩個數進行取反,用&操作符最后用~操作符能恰好解決。
AbsVal函數
absval 函數用于計算一個數的絕對值。它接受一個數值作為輸入,并返回該數值的絕對值。
我們可以先對數值進行左移再取反,最后結合異或操作符,能使函數達到這個功能。
logicalNeg函數
這個函數實現了如果x為0,則結果為0;如果x不為0,則結果為-1的補碼表示。
將上一步的結果+1,得到0或1,就可以實現邏輯非操作。
bitParity函數
這個函數巧妙運用左移和右移操作符。
Byteswap函數
這個函數可以實現字節轉換,我們可以巧妙運用左移和右移操作符,從而實現這個功能。
Getbyte函數
這個函數主要是要知道有效字節的位置,我們用右移操作符和左移操作符尋到最低位置,在用&0xff找到有效位的8位,就是要找的字節。
Isgreater函數
這個函數可以使得返回一個較大的值,類似max。
Isnegative函數
這個函數可以實現判斷輸入整數是否為負數的的操作,負數返回1,其它返回0。
巧妙運用右移操作符和取反,可以達到此效果。
Ispower2函數
這個函數實現判斷x是不是為2的冪的操作。
Addok函數
這個函數可以實現兩個數相加的值,判斷這個值是不是溢出的操作,巧妙運用非操作符可以實現此功能。
Subtractionok函數
這個函數可以發現兩個數的差,有沒有造成溢出的操作,巧妙運用非操作符可以實現此功能。
Oddbits函數
這個函數可以使用位移和按位或運算符來構建出結果,從而返回所有奇數位設置為1的操作
Replacebyte函數
這個函數可以計算出需要進行位移的位數,然后分別創建一個用于清除和設置的掩碼。最后,我們使用這些掩碼對x進行操作,從而實現了替換字節的操作。
Rotateleft函數
這個函數可以使用位操作符 << 來實現左旋轉操作。
Floatabsval函數
這個函數可以檢查絕對值是否大于單精度浮點數表示的最大值,是,說明是NaN,直接返回原始值;不是返回絕對值。就可以實現返回浮點數絕對值的操作。
實驗總結
在實驗過程中,我們首先學習了整數和浮點數的二進制編碼表示,了解了如何將十進制數轉換為二進制數以及如何在計算機中存儲和表示整數和浮點數。我們還學習了如何使用位操作來對二進制數進行操作,例如按位與、按位或、按位異或等。這些操作在計算機底層原理中非常重要,因為它們可以讓我們更深入地理解計算機如何處理數據。我們通過實現一組給定功能的函數來加深對數據二進制編碼表示的了解。這些函數包括加減乘除、位移運算、位操作等。在實現這些函數的過程中,我們不僅學會了如何使用位操作和算術運算來處理數據,還了解了不同類型的數據如何進行比較和運算。通過這次實驗,我們不僅掌握了計算機中整數和浮點數的二進制編碼表示,還學會了如何使用有限類型和數量的運算操作來實現一組給定功能的函數。這些知識和技能對我們今后的學習和工作都具有重要意義,因為它們可以幫助我們更好地理解計算機底層原理、編程和算法設計。
csapp的第一個實驗,函數確實多一點,但是對于學習一些計算機系統的知識還是很有幫助的,希望這篇文章對你有所幫助,加油!