
簡介計算機組成與系統結構袁春風·第三版課后習題答案匯總面向計算機專業(yè)本科生、考研復習者及自學計組、指令系統與匯編語言的人。內容緊密圍繞性能評估、MIPS、CPI、時鐘頻率、性價比分析等高頻考點通過典型習題給出逐步推導與參考答案文檔用多組機器對比、指令條數與執(zhí)行時間表格演示了機器選型、平均時鐘周期數、執(zhí)行時間占比等題型的規(guī)范解法并對易混淆的結論如速度提升百分比和CPI比例做了辨析。資源為一篇doc文檔壓縮包共1個文件、約1.75MB按章節(jié)整理收錄第一、二章等關鍵習題并給出答案要點便于配合教材邊學邊對照、查漏補缺。已有1190人學習下載既適合課后消化例題也適合考前快速梳理重點計算題型。整體是一份緊湊、可復用的計組習題答案解析能幫助讀者在較短時間內掌握性能計算類題目的通用思路。1. 計組課后習題不是背公式為什么指令條數少的程序反而跑得慢計組這門課最容易讓人栽跟頭的地方不是公式記不住而是做題全靠直覺。第三章有一道題很反直覺同一臺機器上指令序列 S2 只有 8 條指令另一個序列 S1 有 10 條結果 S1 跑完只要 38nsS2 卻要花 52ns。指令少的反而慢。這個現象背后正好是計算機組成與系統結構里性能分析的靈魂程序執(zhí)行時間等于指令條數、CPI、時鐘周期三者的乘積。三個變量互相牽制只看其中一個結論就必然翻車。這份課后習題答案匯總的價值也在這里它把基準測試、數據表示、運算機制、校驗原理全部落成了可驗證的數字適合一題一題推演而不是把參考答案背下來。搞懂這些題等于把指令系統底層的設計邏輯重新走了一遍。2. 性能標尺CPU時間、MIPS與性價比如何決定機器選型2.1 CPU執(zhí)行時間的三因子分解任何程序的 CPU 執(zhí)行時間都可以寫成CPU 時間 指令條數 × CPI × 時鐘周期。這里 CPI 是每條指令的平均時鐘周期數時鐘周期是主頻的倒數。三個因子中任何一個變化執(zhí)行時間都會跟著變?;氐搅曨} 9。編譯器把同一段高級語言代碼生成兩個指令序列 S1 和 S2機器主頻都是 500MHz。S1 的 10 條指令里5 條 CPI1、2 條 CPI2、2 條 CPI3、1 條 CPI4算下來 CPI 是 1.9S2 有 8 條指令但 5 條是 CPI4 的 D 類指令CPI 高達 3.25。各自執(zhí)行時間S110 × 1.9 / 500MHz 38nsS28 × 3.25 / 500MHz 52nsS2 指令少了 20%但 CPI 漲了 71%最終執(zhí)行時間反而長了 36.8%。習題答案后面補了一句很關鍵的話并不是指令條數少的目標程序執(zhí)行時間就一定少。這句話值得刻在腦子里。這個公式最大的用途是把“快慢”這種模糊感受拆成可定位的變量。機器慢可以先看主頻是不是低再看程序是不是用了大量高 CPI 的指令最后才看指令條數。很多人調性能一上來就數指令方向就錯了。2.2 MIPS峰值與實際的差距MIPS 是每秒百萬條指令計算公式是指令條數除以執(zhí)行時間再除以 10^6。習題 5 給了兩臺機器跑兩個基準程序的數據???M1 和 M2 跑 P2 的結果M1 是 300×10^3 條指令用 3ms算出來 100MIPSM2 是 420×10^3 條指令用 6ms算出來 70MIPS。從 MIPS 看M1 比 M2 快 1.43 倍。但注意M1 和 M2 的價格分別是 5000 元和 8000 元如果只比 MIPS 就草率選 M1后面性價比那步就會算錯。更迷惑的是峰值 MIPS。習題 6 里M1 主頻 1GHzM2 主頻 1.5GHz但 M2 的各類指令 CPI 都更高。M1 找一段全是 A 類指令的程序CPI1峰值 1000MIPSM2 即使用最快的 A、B 兩類指令因為 B 類 CPI2峰值也只有 750MIPS。主頻更高的機器峰值 MIPS 反而更低因為峰值 MIPS 只反映“這臺機器理論上最快能跑多快”而現實中程序必然混合使用各種指令真實 CPI 一定比最理想情況高。2.3 性價比算術平均與幾何平均誰說了算習題 5 的第四問和第五問是整套答案里設計得很妙的題目。用戶大量使用 P1關心響應時間性價比公式定義為 R 1 /執(zhí)行時間 × 價格。M1 跑 P1 要 10msM2 只要 5ms但 M1 便宜 3000 元。算“執(zhí)行時間 × 價格”M1 是 10 × 5000 50000M2 是 5 × 8000 40000。值越小性價比越高所以選 M2。第五問變成兩個程序同等使用結果就復雜了。用算術平均還是 M2 勝出但用幾何平均sqrt(10 × 0.003) × 5000 小于 sqrt(5 × 0.006) × 8000結論反過來了應該選 M1。同一批數據兩種平均方法給出完全相反的選型建議。算術平均把執(zhí)行時間大的 P1 的差異直接放大幾何平均則削弱了量綱差異帶來的影響。實際做性能選型時選擇哪種平均方式取決于負載特征——如果耗時集中在單個程序算術平均更符合直覺如果是大量同質任務的綜合吞吐幾何平均更能反映真實的感知比。3. 數據表示補碼、移碼與IEEE 754的底層邏輯3.1 補碼為什么減法能變成加法習題 4 列了一組 8 位定點小數要求寫原碼和補碼。比如 -0.1001 的原碼是 1.1001000補碼是 1.0111000。補碼的定義是負數取反加一但這樣定義的原因是為了讓減法統一成加法。CPU 里的加法器只要實現加法減法通過“補碼加一”轉換為加法硬件就能少做一套減法電路。更有意思的是邊界值。同樣的 8 位格式1.0 在原碼和補碼里都溢出因為 7 位數值位最大只能表示 0.1111111不到 1但 -1.0 的補碼 1.0000000 卻能表示。這是補碼特有的不對稱性定點小數的補碼表示范圍是 -1 到 (1-2^-7)負數端比正數端多一個點。習題 6 里給了 [x] 補 10000000求 x答案是 -128也是這個道理。補碼把“0”唯一化了原碼里 0 和 -0 都在補碼里 10000000 不再表示 -0而是整個范圍最左邊的那個負數。3.2 移碼與偏置為什么指數要加127習題 5 讓寫補碼和移碼。1001 的補碼是 00001001移碼是 10001001-1001 的補碼是 11110111移碼是 01110111。對比就能看出來移碼和補碼的區(qū)別只在符號位補碼的符號位取反就是移碼。移碼的核心設計動機是讓階碼可以按無符號數比較大小。浮點數做加減法時要先對階比較兩個指數的大小。如果指數用補碼表示比較大的負數在二進制序里會排在后面比較電路就要額外處理符號。用了偏置常數后指數加上 127或題目里的 16、128最小指數變成全 0最大指數變成全 1大小順序和二進制序完全一致。IEEE 754 選 127 是因為單精度階碼 8 位能表示 -126 到 127全 0 和全 1 另有用途加上 127 后映射到 1 到 254正好避開兩個保留的邊界值。3.3 IEEE 754的隱藏位與漸進下溢習題 7 是這份答案里最值得反復看的一道題。R1 內容 0000108BHR2 內容 8080108BH三條指令把它們當作無符號數、帶符號整數、單精度浮點數真值完全不同。作為浮點數R1 的階碼全 0是非規(guī)格化數沒有隱藏的 1尾數是 0.002116H指數固定為 -126真值是 0.002116H × 2^-126R2 的階碼是 00000001規(guī)格化數尾數里有隱藏的 1指數的真值是 1 - 127 -126結果是 -1.002116H × 2^-126。同一個位模式符號位和階碼差一個 1規(guī)格化狀態(tài)就完全不同。規(guī)格化數隱藏位的設計很精妙規(guī)格化數尾數最高位必然是 1那就干脆不存省下的那一位多存一個有效位。但代價是 0 無法用規(guī)格化表示所以階碼全 0 時改走非規(guī)格化路徑。習題 15 的范圍表里最小非規(guī)格化數是 2^-23 × 2^-126 2^-149而最小規(guī)格化數是 1.0 × 2^-126兩者之間是連續(xù)的、平滑逼近 0 的而不是直接掉到 0。這種“漸進下溢”避免了數值從 2^-126 突然跳成 0 的精度斷層。3.4 大端小端同一個數在不同內存布局下的機器數習題 17 讓畫出 x-0.125、y7.5、i100 在大小端機器上的內存分布。先算出機器數-0.125 是 BE000000H7.5 是 40F00000H100 是 0064H。大端機把最高字節(jié)放在最低地址地址 100 處是 BEH小端機把最低字節(jié)放在最低地址地址 100 處是 00H。這題的陷阱在于很多人以為“大小端只是字節(jié)序顛倒”實際上浮點數的符號位、階碼、尾數在內存里也跟著一起按字節(jié)倒置。x 在地址 100~103在小端機上就是 00H 00H 00H BEH連符號位所在的字節(jié)都被搬到了最后。網絡協議用大端x86 用端小端跨端傳數據時如果直接讀內存字節(jié)符號位、指數位全部錯位這就是為什么序列化要用明確的字節(jié)序約定。4. 運算機制類型轉換、移位、乘除優(yōu)化與檢錯糾錯4.1 unsigned的len-1一個循環(huán)災難的根因習題 9 的 C 程序參數 len 是 unsigned 類型循環(huán)條件是 i len-1。len 為 0 時程序沒有返回 0而是觸發(fā)存儲器訪問異常。float sum_elements(float a[], unsigned len) { int i; float result 0; for (i 0; i len-1; i) result a[i]; return result; }根因是 unsigned 的溢出行為。len0 時len-1 不是 -1而是 0xFFFFFFFF即 unsigned 能表示的最大值。任何有符號的 i 和它比較時i 先被隱式轉換成 unsigned于是 i 永遠小于等于 0xFFFFFFFF循環(huán)體一直執(zhí)行a[i] 越界訪問。修復方法有兩個把 len 聲明成 int或者把測試條件改成 i len。后者更符合直覺因為 i len 在 len0 時直接不進入循環(huán)。這類問題在真實代碼里很常見尤其是把接口里的長度參數寫成 unsigned 又做了 -1 運算的。C 語言的隱式類型轉換規(guī)則決定了有符號和無符號混合比較時有符號會轉成無符號負數的真值瞬間變成幾十億。4.2 邏輯移位與算術移位func1和func2為什么結果不同習題 3 的兩個函數看起來只差一個括號行為卻有本質區(qū)別。int func1(unsigned word) { return (int) ((word 24) 24); } int func2(unsigned word) { return ((int) word 24) 24; }func1 全程按無符號數處理左移 24 位再邏輯右移 24 位相當于把高 24 位清零結果必然是非負的。func2 先把 word 轉成 int左移 24 位后做的是算術右移右移補的是符號位。所以 w0000 0080H 時func1 返回 128func2 先左移得到 80000000H符號位是 1算術右移后得到 FFFFFF80H對應 -128。而 w0000 0100H 時左移 24 位把唯一的 1 移出了 32 位結果是 0。這里值得停下來想一層為什么帶符號整數必須用算術右移因為補碼的負數右移時高位補 0 會讓負數變成正數數值完全錯亂。算術右移保持符號位相當于對負數做向下取整的除以 2 的冪。代價是右移對負數不是向零取整這正好引出下一節(jié)的除法優(yōu)化。4.3 編譯器優(yōu)化乘法如何變成移位與加減習題 5 給了一段反編譯得到的機器代碼要從它反推出原函數里的常量 M 和 N。int optarith(int x, int y) { int t x; x 4; x - t; if (y 0) y 3; y 2; return x y; }x4 是乘 16再減掉原來的 x就是 x×15所以 M15。y2 是除以 4但算術右移對負數向負無窮取整而 C 語言整數除法向零取整所以先給負數加上一個偏置量。y0 時 y3加上 3 之后右移 2 位等價于向零取整的除以 4。為什么要加 3因為 2^2 減 1。對任意負數 y右移 2 位是 floor(y/4)要向零取整就得先把負數墊高 3使得 floor((y3)/4) trunc(y/4)。如果換成偏置 2y-3 時 -32-1右移兩位還是 -1但 -3/4 向零取整是 0就錯了。這道題同時也是指令系統的縮影高級語言里的乘除編譯成一堆移位、加減、條件分支而不是真的調用乘法指令。機器不提供乘除指令程序照樣能跑只是生成的指令序列更長執(zhí)行更慢。4.4 傳輸可靠性奇偶校驗、SEC與CRC怎么工作數據在總線上傳輸時會出錯習題 18、19、20 分別展示了三個層次的檢錯糾錯機制。奇偶校驗最簡單。32 位數據 8F 3C AB 96H 分成四個字節(jié)每個字節(jié)配一個奇校驗位要求每 9 位里 1 的個數為奇數。8F 展開是 1000 1111有 5 個 1校驗位 03C 是 0011 1100有 4 個 1校驗位 1AB 是 1010 1011有 5 個 1校驗位 096 是 1001 0110有 4 個 1校驗位 1。接收端收到的數據變成 87 3C AB 96H校驗位是 0101。重新計算前四個字節(jié)的奇校驗87 只有 4 個 1期望校驗位是 1收到的是 0異或結果為 1定位到第一個字節(jié)出錯。SEC 海明碼更進一步能指出具體哪一位錯。16 位數據的 SEC 碼用 5 個校驗位放在 1、2、4、8、16 位其余位置放數據。每個校驗位覆蓋一組特定位置的數據位出錯時重新計算校驗位和發(fā)送方的校驗位異或得到故障字故障字的二進制值正好是出錯位的編號。習題 19 里數據錯在第 5 位 M5故障字是 01001即 9對應碼字第 9 位——正好是 M5 的位置。這個設計的巧妙之處在于校驗位位置選 2 的冪讓每個出錯位都產生一個唯一的故障字。CRC 校驗則是多項式的世界。習題 20 的數據是 100011生成多項式 G(x)x^31即二進制 1001。發(fā)送方在數據后補 3 個 0用模 2 除法去除以 1001余數是 111CRC 碼就是 100011 111。接收方收到 100010 111同樣做模 2 除法余數 001非 0判定出錯。這里的除法不是算術除法是按位異或相當于判斷接收到的多項式是否能被生成多項式整除。不能整除就說明有錯這正是 CRC 能被廣泛用于鏈路層的原因。5. 常見問題排查計組題里最常翻車的五個現場5.1 現象CPI 直接相比差多少就算快多少習題 6 后面有個思考題程序 P 在 M1 上 CPI 是 2.4M2 上 CPI 是 3.8有人說 M1 比 M2 快 (3.8-2.4)/3.8 36.8%。原因CPI 只是執(zhí)行時間的一個因子這臺題目里 M1 主頻 1GHz、M2 主頻 1.5GHz。完整的執(zhí)行時間是 CPI × 指令條數 / 主頻。假設指令條數為 NM1 是 2.4N nsM2 是 3.8N/1.5 2.53N nsM1 只快約 5%。CPI 直接比錯在丟掉了時鐘周期這一個維度。解決永遠把執(zhí)行時間公式三項寫齊再算任何性能結論都要落到時間上。5.2 現象指令條數少程序一定更快習題 9 的 S1 有 10 條指令S2 只有 8 條S2 反而慢 14ns。原因S2 的 CPI 是 3.25是 S1 的 1.7 倍多出的 D 類指令全是高 CPI 指令。解決比較兩個程序或兩個編譯版本要看 “指令數、CPI、時鐘周期” 的乘積任何單一指標都不能直接證明快慢。5.3 現象十進制小數轉二進制算幾位就停習題 10 里1.7 轉成二進制是無限循環(huán)小數。如果手算時取 0.1101 就收手后續(xù)的階碼、尾數全是錯的。參考答案用 0 舍 1 入得到 0.011011×4^1階碼是 17尾數 0.011011。-0.12 轉出來是 -0.000111101B要左移到 0.011111×4^-1 再取補碼。原因浮點格式尾數位有限十進制小數在二進制里可能無限循環(huán)必須按格式位數做舍入。解決先確定格式有多少位尾數再決定保留幾位最后一步做 0 舍 1 入不要提前截斷。5.4 現象unsigned 的邊界值當普通整數算習題 9 的 len0 時len-1 是 0xFFFFFFFF 而不是 -1循環(huán)不退出。習題 8 里 -1 0U 的結果是 0因為 -1 轉成 unsigned 后是 4294967295。原因C 語言的隱式類型轉換把有符號轉成無符號負數變成大正數。解決涉及 unsigned 的循環(huán)條件不用 len-1 這種寫法直接 i len混合比較時先想清楚兩邊會被轉換成什么類型。5.5 現象除法優(yōu)化偏置量想當然習題 5 的 y/4 優(yōu)化有人覺得負數加 2 就行。加 2 對 y-4 恰好成立但對 y-3 就錯了-32-1算術右移兩位是 -1而 -3/4 向零取整是 0。原因偏置量必須是 2^k - 1目的是讓 floor((ybias)/2^k) 等于 trunc(y/2^k)。解決不要背特例直接從向下取整和向零取整的關系推k 位右移配 2^k - 1 的偏置。6. 設計取舍每個聰明的設計都在“浪費”位寬這套習題答案看下來會發(fā)現一個規(guī)律計算機里每個關鍵設計都在用某種“浪費”換另一種收益。補碼浪費了直觀性換來的是加減法統一CPU 里少一套減法器移碼浪費了純二進制的大小順序直覺換來浮點指數可以直接按無符號數比較IEEE 754 浪費了規(guī)格化數尾數最高位的一位空間但把這一位變成隱藏位多給了 24 位有效精度非規(guī)格化數浪費了指數編碼空間換來的是下溢時數值能平滑逼近 0而不是從 2^-126 直接跳成 0。這些取舍在習題里體現得非常具體。習題 4 里 1.0 溢出而 -1.0 不溢出就是補碼不對稱性的代價習題 15 里最大規(guī)格化數和最小非規(guī)格化數相差那么多數量級就是浮點表示把范圍撐大后精度分布不均的代價。做題的時候如果不看設計動機這些邊界情況都像冷門考點但一旦理解了“每個位模式都有它的用途和代價”它們就成了驗證設計合理性的檢查點。從那以后我每次拿到一道計組題都強制自己先列出參與計算的公式和前提再代入數值最后才看結論。尤其是性能題和浮點題直覺幾乎總是錯的公式和位模式才是唯一可靠的工具。這份習題答案匯總適合放在手邊邊做邊對照把每一道題的“為什么”推演一遍比直接背參考答案有用得多。希望幫到你。本文還有配套的精品資源點擊獲取