二進制反碼求和運算


  (2019年2月19日注:這篇文章原先發在自己github那邊的博客,時間是2016年7月12日)

  周四要給工作室的小朋友們繼續培訓計算機網絡,要講的內容是傳輸層,於是今天就在准備相應的材料,重新看回謝希仁老師的課本過程中又加深了一點理解,然后看到了當時碰到的第一個難點,UDP協議的校驗和的計算

  其實本質上來說這個計算原理還是不難的,就是一個二進制反碼求和運算,具體來說就是:$$0+0=0$$ $$1+0=0+1=1$$ $$1+1=10$$

  其中10中的1加到了下一列去,如果是最高列的1+1,那么得到的10留下0,1移到最低列,與最低位再做一次二進制加法即可。

  在謝老師的這本書里,講到的是一個15字節的UDP數據在發送方怎么進行數據的檢驗,然后列出了一個二進制的豎式並給出一個結果,然而並沒有講述是怎么計算出來的。經過我不斷的努力,終於把二進制計算的過程整個寫出來了。之前在數計院上課的時候,老師講過一個較為之簡單的十六進制計算法,對比之下確實是簡單很多。好了,先上圖。

 

 

  謝老師在課本里面給出的題目是這樣子的。

二進制版
1001 1001 0001 0011 //偽首部源IP地址前16位
0000 1000 0110 1000 //偽首部源IP地址后16位
1010 1011 0000 0011 //偽首部目的IP地址前16位
0000 1110 0000 1011 //偽首部目的IP地址后16位
0000 0000 0001 0001 //偽首部UDP協議字段代表號17,前面8位是填充0
0000 0000 0000 1111 //偽首部UDP長度字段
0000 0100 0011 1111 //UDP頭部源IP地址對應的進程端口號
0000 0000 0000 1101 //UDP頭部目的IP地址對應的進程端口號
0000 0000 0000 1111 //UDP頭部UDP長度字段
0000 0000 0000 0000 //UDP頭部UDP檢驗和
0101 0100 0100 0101 //數據字段
0101 0011 0101 0100 //數據字段
0100 1001 0100 1110 //數據字段
0100 0111 0000 0000 //數據字段+填充0字段
   
十六進制版
9913        //偽首部源IP地址前16位
0868        //偽首部源IP地址后16位
AB03        //偽首部目的IP地址前16位
0E0B        //偽首部目的IP地址后16位
0011        //偽首部UDP協議字段代表號17,前面8位是填充0
000F        //偽首部UDP長度字段
043F        //UDP頭部源IP地址對應的進程端口號
000D        //UDP頭部目的IP地址對應的進程端口號
000F        //UDP頭部UDP長度字段
0000        //UDP頭部UDP檢驗和
5445        //數據字段
5354        //數據字段
494E        //數據字段
4700        //數據字段+填充0字段

 

  在二進制版中,是不可以直接從右邊第一列開始做豎式相加的,不要說十進制的豎式相加,二進制的豎式相加都做不到。

      正確的做法是:
      (1) 讓第一行和第二行做二進制反碼運算。
      根據上述的規則,當碰到1+1=10時,在左鄰側一列下面寫個小1(類似以前做十進制進位加法),然后側列進行二進制反碼運算得出一個數,如果沒有進位,就繼續與剛才的進位做二進制反碼運算,如果有進位,則先把進位的小1寫在相鄰高側列的下方,取個位來與其相加。有進位的只有1+1=10的情況,0不論加什么進位都不會有進位,而如果第一次計算沒有進位時,只有產生1的情況下才會有進位,總而言之,對於每一列,都只會有至多一次的進位,所以不用擔心進位會跨列的問題。這樣子做要注意的就是不要寫錯數字了,比如我自己在寫這張紙之前已經打過兩次草稿了,然而還是會寫錯。
      對於高位有1的情況,就是把1挪到最低位,再做一次二進制反碼計算,本質來說就是取補碼。
      (2) 將第一行和第二行的結果與第三行做二進制反碼計算,以此類推。
      (3) 運算結果取反,得到校驗和。

      在十六進制版中,運算量會大大減小,主要的計算步驟如下:
      (1) 從右邊第一列開始,按照十進制來計算第一列的值。
      在這里第一列算出來是107,寫成8位二進制就是01101011。
      (2) 根據算出來的結果分成兩部分,左邊的4位化成十進制,作為下一列進位時加的數,右邊4位化成16進制,作為第一列的結果。
      這里就是610B16,圖片誤算成D,6作為下一列運算時要加上的對象,B作為第一列的結果。
      (3) 十進制計算第二列的結果,加上第一列得到的進位得到第二列的一個十進制數字,化為二進制,根據第二步來進行判斷,依次類推。
      在這里第二列算到的是24,加上6就是30,化為8位二進制就是00011110,也就是1E,第二列的結果為1,第三列的十進制進位為1。接着可以算到第三列的結果為6,十進制進位為4。
      (4) 最高位算出最后的十進制結果后,化為二進制時,右邊4位作為最終結果,左邊4位移入下一列,用上一步得到的結果96EB,加上0010,得到最后結果,這里圖片的最后一步寫錯了,不應該舍棄。
      最后能得到結果為96ED。
      (5) 結果取反,得到校驗碼。
      校驗碼為6912。

      好了這次先針對這個特定的問題提出了解決方案,有時間要好好整理下關於計算機的原碼、反碼和補碼的知識。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM