1. 程式人生 > >CSAPP(深入理解計算機系統)

CSAPP(深入理解計算機系統)

前言

自己這段時間上了微機原理,想起來這本書也看完了,就一同綜合做個筆記。因而有部分是隻屬於MIPS的,我會標註出來,如果不需要應付考試的話我是不推薦讀裡面相關段落的一個字的,而為應付考試的話標註屬於MIPS的應為重點,利用crtl +F 搜尋MIPS即可

第二章:資訊的表示與處理

總綱

主要是二進位制的位元串的存放規則與譯碼規則的不同

2.1資訊儲存

2.1.1 位元組

儲存的基本單元:

  • 大多數計算機利用8位的塊(位元組byte)來作為最小的可定址的儲存器單位

即如地址0x00000001 中儲存了0xcc 這樣的資料

2.1.2 字

字:

  • 每臺計算機擁有字長(word size)指明整數與指標資料的表稱大小,也就是CPU一次能處理的位數
  • 同時也是虛擬地址的定址空間

2.1.4 定址與位元組順序

定址:

  • 多位元組物件被儲存為連續的位元組序列,物件的地址為所使用的位元組中最小的地址

如int x地址為0x100; 即&x = 0x100,x的四個位元組儲存在0x100 0x101 0x102 0x103

  • 位元組順序(大端機與小端機):

大端機:最高有效位元組在最前面
小端機:最高有效位元組在最後面
如 0x01234567 高位是0x01 低位是0x67

地址 0x100 0x101 0x102 0x013
大端機 0x01 0x23 0x45 0x67
小端機 0x67 0x45 0x23
0x01

- show_bytes程式

  //可用於按位模式顯示資料
  #include<stdio.h>
  typedef unsigned char *byte_pointer;

  template <typename T>
  void show_bytes(T x)
  {
    byte_pointer start = (byte_pointer)&x;
    for (int i =0;i<sizeof(T);++i)
    {
        printf("%.2x", start[i]);
    }
    printf
("\n"); }

2.1.10位移運算

  • 左移k位:丟棄最高的k位,右端補零
  • 右移k位:邏輯右移:左端補0

    ​算術右移:左端補1 (有符號數幾乎都是用算術右移)

  • Attention: 加減優先順序比位移高

2.2 整數表示

注意,以下僅討論整數,那麼提升,擷取等都只對整數而言.

2.2.2 無符號數編碼

B2Uw(BinaryToUnsigned)B2Uw(x⃗ )=.i=0w1xi2i

2.2.3 補碼編碼

B2T_w(Binary to Two’s-complement)

B2Tw(x⃗ )=.xw12w1+i=0w2xi2i

反碼與原碼

  • 反碼(Ones’ Complement): 為 補碼 的最高有效位的權 小一

    B2Ow(x⃗ )=.xw1(2w11)+i=0w2xi2i
  • 原碼(Sign-Magnitude):最高有效位是符號位,用於確定剩下的位應該取正還是負

B2Sw(x⃗ )=.(1)xw1.i=0w2xi2i
  • 原碼,反碼,補碼關係

    • 正數: 三者相同
    • 負數:
    • 反碼: 原碼符號位以外的各位求反
    • 補碼: 原碼除符號位外取反(反碼)後在末尾加1

2.2.4 有符號數與無符號數之間的轉換

強制型別轉換: 結果保持位值不變,只是改變了解釋這些位的方式

Attention: 隱式/顯示 型別轉換 見Cpp_Prime 4.11 Type Conversions 筆記

2.2.6 擴充套件一個數字的位表示

  • 零擴充套件(zero extension):將無符號數變大,在開頭添0
  • 符號擴充套件(sign extension):補碼數字變大,新增 最高有效位值 的副本

2.2.7 截斷數字

簡單的丟棄掉前面多的位數.

2.3 整數運算

  • 就是進行位級別的運算,只是注意溢位,這裡給出一個例子
#include <iostream>
using namespace std;
float sum_elements(float a[], unsigned length)
{
    float sum = 0;
    for (int i=0;i<= length-1;++i)//由於length 為unsigned,當length=0時,length-1會下溢
    {
        sum += a[i];
    }
    return sum;
}
int main()
{
    float x[4] = { 1.0,2.0,3.0,4.0 };
    cout << sum_elements(x, 0) << endl;
}
  • 關於乘以常數,可以利用位運算加速,如x14=x(2421)=(x<<4)(x<<1)

2.4 浮點數

2.4.2 IEEE浮點數表示

這裡先給出數學表示式,再講述其中符號的意思,再說明如何自己譯碼並進行計算.

  1. 數學表達
V=(1)s×M×2E
  1. 符號解釋

    • 符號(sign) s

    • 尾數(significand) M

    • 階碼(exponent) E

    將浮點數的位表示劃分為三個欄位,分別為這些值進行譯碼

    • 一個單獨的符號位s直接編碼符號s
    • k位的階碼欄位, exp=ek1...e1e0 編碼階碼E
    • n位小數字段frac=fn1...f1f0編碼尾數M,但其也依賴於階碼欄位的值

單精度float 32位 各個欄位

31 30 23 22 0
s exp frac

​ 雙精度double 64位 各個欄位

63 62 52 51 0
s exp frac

3. 譯碼

以float說明如何解釋各個欄位並讀出十進位制值這裡記住偏置Baias=2k11

  1. 格式化的值(即階碼為不為全0 或者全1)那麼階碼為將階碼段值以無符號解釋出來(設為e)後減去偏置 即 E=eBias 小數字段frac為描述小數值f=0.fn1...f1f0 此時的尾數M=1+f 即自帶了一個整數1
  2. 非格式化的值(階碼為全0) 此時 E=1BiasM=f, 注意此時不包含隱含的1
  3. 無窮大(階碼全為1 並且 小數段全為0)
  4. NaN(階碼全為1 但是 小數字段不為全0) 不是數

2.4.5 浮點運算(與補充)

由於以下運算步驟,因而1+1e120-1e120 = 0,而1e120-1e120+1 = 1

加減計算方式

大體分為六步

  1. 0運算元檢查
  2. 比較階碼,並完成對階碼
  3. 尾數求和運算
  4. 結果規格化
  5. 舍入處理
  6. 溢位處理

這裡用一個例子綜合地回顧浮點數的表示與運算(also MIPS)

1.3+3.7

  1. 1.3(float表示):易知s = 0

    1.3二進位制數為1.3_d = 1.0 1001 1001 1001 10011001 1001..._b那麼為規範數.

    其階碼為0,加上偏置(bias = 127) 得到階碼位為127_d = 0111 1111_b

    然後其小數位就需要去除整數部分的1,然後進行舍入到23位,為0 1001 1001 1001 1001 1001 10

    最後其二進位制表示就是0(符號位)0111 1111(階碼位)0 1001 1001 1001 1001 1001 10

    整理為16進位制就是0x3fa66666 在小端機上就會顯示為0x66 66 a6 3f

  2. 3.7(float表示):易知 s= 0

    3.7二進位制數為3.7_d = 11.1 0110 0110 0110 0110 0110 0110 0110..._b那麼為規範數

    小數點需左移一位,那麼階碼為1,加上偏置得到階碼位128_d = 1000 0000_b

    左移後數為1.11 0110 0110 0110 0110 0110 0110 0110..._b

    然後進行小數位舍入得到11 0110 0110 0110 0110 0110 1注意左後的1是舍入得到的

    最後其二進位制表示就是0(符號位)1000 0000(階碼位)11 0110 0110 0110 0110 0110 1

    整理為16進位制就是0x406ccccd 在小端機上就會顯示為0xcd cc 6c 40

  3. 1.3 + 3.7 相加

    1. 均不為0

    2. 1.3階碼小,進行對階,將小數部左移1位,相當於

      210.101001100110011001100110...
    3. 此時再將位數相加,這裡要注意3.7尾數前有隱含的1,而1.3對階後沒有了隱含的1,那麼相當於

      1.1101 1001 1001 1001 1001 101 + 0.1010 0110 0110 0110 0110 011

      的到10.1000 0000 0000 0000 0000 000

    4. 規範化,由上一步算出來的式子還需要左移一位得到規範的尾數,那麼階碼+1 得到為2 加上偏置為129.

      階碼 129_d =1000 0001尾數變為010 0000 0000 0000 0000 0000

      得到結果為0 1000 0001 010 0000 0000 0000 0000 0000 16進製為0x40 a0 00 00

第三章:程式的機器級表示

總綱

當做一門新的語言來,但是是一門貼近硬體的底層語言,在應用過程中加深對底層架構的理解。像硬體應用開發一樣,直接操作暫存器,記憶體。

MIPS的彙編

3.0.1 彙編基本概念

  • 彙編: 把組合語言翻譯為機器語言的過程
  • 彙編程式:實現彙編過程的軟體程式
  • 指令: 計算機能執行的程式碼的最小單位
  • 程式: 指令的有序組合
  • 指令集: 計算機能執行的所有的指令的集合

3.0.2 常用指令集和(複習用)

3.0.3 資料儲存方式

  • 資料存放採取位元組對齊: 半字型別資料從偶地址開始存放,字型別從4的整數倍地址開始存放
  • 由於為精簡指令集,指令長度都為32位即佔