1. 程式人生 > >二進制反碼求和運算

二進制反碼求和運算

留下 auto 原碼 就是 朋友 進程 根據 進行 有時

  (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。

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

二進制反碼求和運算