20135321餘佳源——信息安全系統設計基礎第三週學習總結

信息安全系統設計基礎第三週學習總結 算法

第四周:學習任務教材第二章 編程

 

第四周(9.28-10.04): 數組

學習計時:共10小時 安全

讀書:2 網絡

代碼:2 數據結構

做業:3 函數

博客:3學習

學習目標測試

1. 理解二進制在計算機中的重要地位 編碼

2. 掌握布爾運算在C語言中的應用

3. 理解有符號整數、無符號整數、浮點數的表示

4. 理解補碼的重要性

5. 能避免C語言中溢出,數據類型轉換中的陷阱和可能會致使的漏洞

 

學習任務:

 

公式能夠不看,習題不能不作,考覈題目和課後習題相似,重點題目:

 

2.四、2.六、2.八、2.十一、2.1三、2.1四、2.1八、2.1九、2.2一、2.2三、

 

2.2四、2.2五、2.2七、2.2九、2.3三、2.3四、2.3九、2.40、2.4二、2.4三、

 

2.4四、2.4五、2.4七、2.50、2.5二、2.54

 

 

 

p20: 三種數字:無符號數、有符號數(2進制補碼)、浮點數,信息安全系同窗從逆向角度考慮爲何會產生漏洞

 

p22: 進制轉換,注意拿二進制做中間結果就好轉了

 

p25: gcc -m32 能夠在64位機上(好比實驗樓的環境)生成32位的代碼

 

p26: 字節順序是網絡編程的基礎,記住小端是"高對高、低對低",大端與之相反就能夠了。

 

p28: 代碼執行一下

 

p32: 能區分邏輯運算(結果是1或0)和位運算(結果是位向量),全部邏輯運算均可以用與、或、非表達(最大式、最小式),而與或非能夠用"與非"或"或非"表達,因此,只要一個與非門,就能夠完成全部的邏輯運算。

 

p33: 掩碼是位運算的重要應用,對特定位能夠置一,能夠清零

 

p38: 要用C99中的"long long"類型,編譯是要用 gcc -std=c99

 

p39: 補碼的利用寄存器的長度是固定的特性簡化數學運算。想一想鐘錶,12-1 等價於 12 + 11,利用補碼能夠把數學運算統一成加法,只要一個加法器就能夠實現全部的數學運算。

 

p44: 注意C語言中有符號數和無符號數的轉換規則,位向量不變。想一想第一章說的 信息就是"位+上下文"

 

p48: 怎麼樣讓負數等於正數? 信息安全的逆向思惟

 

p49: 0擴展和符號擴展

 

p52: 深刻思考一下代碼和結果

 

p54: 如何讓整數運算溢出?如何避免?

 

p62例子看看

 

p67: 關於整數運算的最後思考

 

p67: 浮點數有科學計數法的基礎就不難理解,IEEE標準754

 

p68: 浮點數運算的不精確性與舍入

 

p70: IEEE浮點標準,float/double類型

 

p74: 整數與浮點數表示同一個數字的關係

 

p78: 整數與浮點數轉換規則

 

p80:家庭做業能夠選作,協調好每題最多兩人一組作,一星題目一人加一分,二星加二分,三星加三分,四星加四分

 

 

筆記:

1.三種數字:無符號數、有符號數(2進制補碼)、浮點數,信息安全系同窗從逆向角度考慮爲何會產生漏洞

無符號數:基於傳統的二進制表示法,表示大於或者等於零的數字。

補碼:表示有符號整數最多見的方法,能夠爲正能夠爲負。

浮點數:表示實數的科學計數法。

結果太大可能會使得某些運算溢出,大量的計算機安全漏洞是因爲計算機算術運算的微妙細節引起的。

 

2. 進制轉換,注意拿二進制做中間結果就好轉了

四位二進制等於一位十六進制,2的n次冪換算十六進制,

練習題2.4:

0x503c+0x8=0x5044

0x503c-0x40=0x4ffc

0x503c+64=0x507c

0x50ea-0x503c=0xae

 

3. gcc -m32 能夠在64位機上生成32位的代碼

 

4. 字節順序是網絡編程的基礎,記住小端是"高對高、低對低",大端與之相反就能夠了。

小端法:最低有效字節在最前面的方式

大端法:最高有效字節在最前面的方式

也有雙端法。

已知,Linux 3二、 Windows、Linux 64是小端法機器。Sun是大端法機器。

 

5. p28的代碼,使用強制類型轉換來訪問和打印不一樣程序對象的字節表示。

代碼以下:

執行一下,達到以下結果:

練習2.6:

A:0000 0000 0011 0101 1001 0001 0000 0001

0100 1010 0101 0110 0100 0101 0000 0100

B:右移兩位可最大又21位匹配

C:除了最高有效位1,整數的全部位都嵌在浮點數中,而浮點數有一些非零的高位不與整數中的高位相匹配

 

6. 能區分邏輯運算(結果是1或0)和位運算(結果是位向量),全部邏輯運算均可以用與、或、非表達(最大式、最小式),而與或非能夠用"與非"或"或非"表達,因此,只要一個與非門,就能夠完成全部的邏輯運算。使用掩碼,利用位向量來對集合編碼。掩碼是位運算的重要應用,對特定位能夠置一,能夠清零。

練習2.8:

a 01101001

b 01010101

~a 10010110

~b 10101010

a&b 01000001

a|b 01111101

a^b 00111100

 

7. 要用C99中的"long long"類型,編譯是要用 gcc -std=c99,C語言定義了每種數據類型必須可以表示的最小的取值範圍。C和C++都支持有符號和無符號數,JAVA只支持有符號數。

練習2.11:

  1. k
  2. 此時first=last=3,因此a[3]^a[3]=0
  3. 第4行修改爲first<last即本身不須要與自己交換

練習2.13:

bis(x,y)

bis(bic(x,y),bic(y,x))

bis(x,y)實際上是保留x的1,加入了y的1,也就是"或"。

練習2.14:

x&y 0x20 x&&y 0x01

x|y 0x7F x||y 0x01

~x|~y 0xDF !x||!y 0x00

X&!y 0x00 x&&~y 0x01

 

8. 補碼的利用寄存器的長度是固定的特性簡化數學運算。相似於鐘錶,12-1 等價於 12 + 11,利用補碼能夠把數學運算統一成加法,只要一個加法器就能夠實現全部的數學運算。對於某些程序來講,用某個肯定大小的表示來編碼數據類型很是重要,好比Java標準很是明確,採用補碼錶示,單字節數據類型成爲byte而不是char且沒有long long數據類型。所以保證了Java程序在不管什麼機器上都能表現得同樣。

 

9. 有符號數還有兩種標準的表示方法:反碼和原碼。C語言容許在各類不一樣的數字數據類型之間作強制類型轉換,且支持全部整型數據類型的有符號和無符號運算,一般大多數數字都默認爲有符號的。注意C語言中有符號數和無符號數的轉換規則,位向量不變。信息就是"位+上下文"。

練習2.18:

A:440 B:20 C:-424 D:-396 E:68 F:-312 G:16 H:12 I:-276 J:32

練習2.19:

x 

hex(x) 

T2U4(x)

-8 

0x8 

8 

-3 

0xD 

13 

-2 

0xE 

14 

-1 

0xF 

15 

0 

0x0 

0 

5 

0x5 

5 

 

 

10.怎麼樣讓負數等於正數? 信息安全的逆向思惟

    利用printf首先將一個字當作一個無符號數輸出,而後再把它當作一個有符號數輸出。轉換的原則是底層的位表示保持不變。就是應用函數U2TW,將無符號數轉換爲有符號數。

練習2.21:

類型

求值

無符號數

1 

有符號數

1 

無符號數

0 

有符號數

1 

無符號數

1 

 

 

11. 0擴展和符號擴展

0擴展:將一個無符號數轉換爲一個更大的數據類型,在表示的開頭添加0.

符號擴展:將一個補碼數字轉換爲一個更大的數據類型。

練習2.23:

A:fun1是無符號移位,即邏輯移位,fun2則是算數移位

W

fun1(w)

fun2(w) 

0x00000076 

0x00000076 

0x00000076 

0x87654321 

0x00000021 

0x00000021 

0x000000C9 

0x000000C9 

0xFFFFFFFC9 

0xEDCBA987 

0x00000087 

0xFFFFFFF87 

B:fun1從參數的低8位中提取獲得範圍0-255之間的整數,fun2也是從低8位提取,可是進行了符號擴展,因此是介於-128~127

 

12. 深刻思考一下代碼和結果

    當參數length爲0時,程序代碼會出錯,說明從有符號數到無符號數的隱式強制類型轉換很容易引起錯誤。因爲length在代碼中是無符號的,0-1將會進行無符號計算,就會等價於MOD算法,至關於獲得一個MAX數值,因此全部數都是小於等於MAX值的,因而老是爲真。因此代碼嘗試訪問數組a的非法元素。

練習2.24:

無符號截斷值

補碼截斷值

0 

0 

2 

2 

1 

1 

3 

3 

7 

-1 

練習2.25:

出錯緣由:當參數length爲0時,程序代碼會出錯,說明從有符號數到無符號數的隱式強制類型轉換很容易引起錯誤。因爲length在代碼中是無符號的,0-1將會進行無符號計算,就會等價於MOD算法,至關於獲得一個MAX數值,因此全部數都是小於等於MAX值的,因而老是爲真。因此代碼嘗試訪問數組a的非法元素。

修改辦法:將length聲明爲int類型進行有符號運算,或者將for循環的測試條件改成i<length防止溢出

 

13. p54: 如何讓整數運算溢出?如何避免?

    首先,無符號數運算:全部無符號數運算都是以2的n次方爲模,(n是結果中的位數)。因此它不存在運算時的沒有那種所謂的"溢出",當它超過範圍時,從零開始從新計數!當一個無符號數和有符號數相加的時候,有符號數會自動轉化爲無符號數參與運算!

    其次,有符號數運算: 是可能發生"溢出"的,並且溢出的結果是未定義的。當一個運算的結果發生溢出時,作出任何假設都是不安全的。

    避免方法:檢查 cpu 的狀態標誌寄存器中的溢出標誌位,驗算運算是否超出了溢出標誌位。

練習2.27:

int fun(unsigned x,unsigned y){

    unsigned sum=x+y;

    return sum>=x;

}

練習2.29:

x 

y 

x+y 

x+(t/5)y 

狀況

[10100] 

[10001] 

100101

00101 

1 

[11000] 

[11000] 

110000 

10000 

2 

[10111] 

[01000] 

111111 

11111 

2 

[00010] 

[00101] 

000111 

00111 

3 

[01100] 

[00100] 

010000 

10000 

4 

練習2.33:

x

-(t/4)x

十六進制

十進制

十進制

十六進制

0

0

0

0

5

5

-5

B

8

-8

-8

8

-3 

-1 

練習2.34:

x·y

截斷的x·y

20[010100]

12[001100] 

4[100]

-4[100] 

14[001110]

-2[111110] 

6[110]

-2[110] 

36[100100]

4[000100] 

4[100]

-4[100] 

 

 

14. p62 XDR庫中的安全漏洞

    參數過大,第10行上的乘法運算會溢出,從第16行開始的循環會試圖複製全部字節,超出已分配的緩衝區的界限,從而破壞其餘的數據結構,致使程序崩潰或者行爲異常。可見malloc使用了一個32位無符號數做爲參數,所以不可能分配一個大於232個字節的塊,因此不必,應該將其放棄,返回一個NULL。

練習2.39:

將表達式變爲-(x<<m),設字長w,n=w-1。計算(x<<w)-(x<<m),而將x向左移動w位會獲得0。

練習2.40:

表達式

(x<<2)+(x<<1) 

(x<<5)-x 

(x<<1)-(x<<3) 

(x<<6)-(x<<3)-x 

練習2.42:

int div16(int x){

    int bias=(x>>31)&0xF;

    return (x+bias)>>4;

}

練習2.43:

M=31,利用(x<<5)-x求x*M

N=8,y是負數時加上偏置量7,且右移3位

 

15.關於整數運算的最後思考

    計算機執行的"整數"運算其實是一種MOD運算形式,表示數字的有限字長限制了可能的值的取值範圍,致使運算結果溢出。補碼提供了一種既能表示負數又能表示整數的靈活方法。C語言中某些規定可能會產生出乎意料的結果,並且難以察覺,unsigned

數據類型概念上簡單,卻可能致使不少意想不到的行爲。

練習2.44:

A:假。令x=TMin32,x-1=TMax32

B:真。前式爲0則有位x2等於1,左移29位後,x2將會成爲符號位

C:假。令x爲0xFFFF,x*x爲0xFFFE0001.

D:真。X非負數,-x是非正。

E:假。令x=TMin32,那麼x與-x都是負數

F:真。

 

G:真。~y=-y-1.uy*ux=x*y,因此等價。

 

16. 浮點數有科學計數法的基礎就不難理解,IEEE標準754

 

17.浮點數運算的不精確性與舍入

    二進制表示法只能表示那些可以被寫成x*2y的數,其它的值只能被近似表示。增長二進制的表示長度能夠提升表示的精度。

練習2.45:

小數值

二進制表示

十進制表示

1/8

0.001 

0.125 

3/4

0.11 

0.75

25/16

1.1001 

1.5625 

43/16

10.1011 

2.6875 

9/8

1.001 

1.125 

47/8

101.111 

5.875 

51/16

11.0011 

3.1875 

 

 

18. IEEE浮點標準,float/double類型

    IEEE浮點標準用V=(-1)S*M*2E的形式來表示一個數:符號s決定正負,對於數值0的符號位解釋做爲特殊狀況處理。尾數M是一個二進制小數。階碼E做用是對浮點數加權,權重是2的E次冪。

    浮點數的位劃分三個字段,分別對這些值進行編碼:

一個單獨的符號位s直接編碼符號s

K位的階碼字段編碼階段E

N位小數字段編碼尾數M

    兩種最多見的格式就是float 和double,區分一下單精度和雙精度的具體狀況。

練習2.47:

見書本。

 

19.整數與浮點數表示同一個數字的關係:相關的區域對應整數的低位,恰好在等於1的最高有效位以前中止,也就是隱含的開頭的位1,與浮點數表示的小數部分的高位時相匹配的。

練習2.50:

原始值

舍入後的值

10.0102 2+(1/4)

10.0 2

10.0112 2+(3/8)

10.1 2+(1/2)

10.1102 2+(3/4)

11.0 3

11.0012 3+(1/8)

11.0 3

練習2.52:

1011110

15/2

1001111

15/2

0101001

25/32

0110100

3/4

1101111

31/2

1011000

16

0000001

1/64

0001000

1/64

 

 

20.整數與浮點數轉換規則

  • 從int轉換成float,數字不會溢出可是可能被舍入。
  • 從int或者float轉換成double,能保留足夠精確的數值
  • 從double轉換成float,可能溢出成正無窮或負無窮,因爲精確度較小,還可能被舍入
  • 從float或者double轉化成int,值會向零舍入,也就是可能溢出。一個浮點數向整數轉換,若是不能爲該浮點數找到一個合理的整數近似值,就會產生整數不肯定值。

練習2.54:

A:真,double比int具備更大的精度和範圍

B:假,令x=TMax即爲假

C:假,令d=le40,右邊可獲得正無窮

D:真,double比float具備更大的精度和範圍

E:真,浮點數取非就是對他的符號位取反

F:真,這是浮點數的除法

G:真

H:假,令f爲1.0e20而d爲1.0,f+d會舍入到1.0e20,左式所以求得0.0而右式爲1.0。

 

 

 

家庭做業:

2.65 寫出代碼實現以下函數:

/*Return 1 when x contains an even number of 1s; 0 otherwise. Assume w=32*/

int even_ones(unsigned x);

函數應該遵循位級整數編碼規則,不過你能夠假設數據類型int有w=32位,你的代碼最多隻能包含12個算術運算、位運算和邏輯運算。

解讀題目:當無符號數x包含偶數個1時,返回值爲1,不然爲返回值爲0,假設x的數據類型是int 有w=32位。

解題思路:要求x所包含的1的個數,能夠對x的每一個位進行異或運算。若是獲得的結果是0,那麼就說明x包含偶數個1,則返回值爲1,;若是獲得的結果是1,那麼說明x包含奇數個1,則返回值爲0。

代碼編寫過程:因爲x是個32位int類型數,因此①首先採用折半縮小規模的方法進行逐位異或。②最後獲得的x值再與1進行與運算就會獲得一個32位中前31均爲0,尾數是0或者是1(用於判斷是原x包含奇數仍是偶數個1),③返回這個值就完成了題目需求。

代碼編寫:

int even_ones(unsigned x){

x ^= (x >> 16);//等同於x=x^(x>>16)

x ^= (x >> 8); //等同於x=x^(x>>8)

x ^= (x >> 4); //等同於x=x^(x>>4)

x ^= (x >> 2); //等同於x=x^(x>>2)

x ^= (x >> 1); //等同於x=x^(x>>1)

return !(x&1);

}

 

 

 

遇到的問題及解決:

  1. 一開始對算數移位和邏輯移位混淆,不知道在右移的時候應該補1仍是0。

    解決:在類似的重複的練習中摸清楚了算數移位是須要補1而邏輯移位須要補0

  2. 在練習2.13中遇到的兩個幾乎陌生的函數bis和bic,僅用兩個陌生的函數就能夠作到or和xor的功能讓我無所適從。

    解決:我在草稿紙上根據bis和bic的功能假設了兩個8位二進制數,經過bis和bic

    的運算來摸清他們之間的規律。

  3. 對於計算機計算"整數"的MOD算法實際上是抱有疑惑,不能很好地判斷究竟是何時會溢出,使得數據結構損壞。

    解決:只好經過作幾道練習題來稍稍瞭解。

  4. 家庭做業中,一開始就懵逼了,題目很簡單,可是作起來缺沒用想象中那麼容易,由於我只是隱約記得之前在C語言中好像學過是有經過位運算來斷定所包含的1或者0的個數。

    解決:通過搭檔符運錦同窗給個人題目解析和解題思路,我根據逐位異或的算法把這道家庭做業的代碼寫了出來。截圖:

    結果:

    即當a爲10e5+0時,返回值爲0

    若a爲10e5+1時,返回值爲1

相關文章
相關標籤/搜索