六星經典CSAPP筆記(2)資訊的操作和表示

來源:互聯網
上載者:User

標籤:

2.Representing and Manipulating Information本章從二進位、字長、位元組序,一直講到布爾代數、位元運算,最後無符號、有符號整數、浮點數的表示和運算。誠然有些地方的數學證明有些枯燥,但總體上看,本章還是乾貨十足的!
2.1 Decimal vs. Binary Notation
我們習慣十進位只是因為我們有十根手指頭(?),所以會對二進位感到不習慣。但是 二值訊號(two-value signal)在表示、儲存、傳輸方面有巨大優勢,從打孔帶上的有沒有孔洞(代碼的表示),到電線上的高低電壓(資料的傳輸),到磁疇(magnetic domain)的順時針、逆時針旋轉(磁碟上儲存)
2.2 Words
字長是CPU一次能夠處理的資料長度,一般代表著能處理的數字長度,也代表了CPU資料通路的寬度(地址匯流排、資料匯流排)。
2.3 Addressing & Byte Ordering
位元組序,大尾端小尾端,這些耳熟能詳的詞彙,彷彿已經翻來覆去學了好多回都要爛熟如心了。可這東西到底有什麼用啊?答案是用處大著呢:
  • 不同機器間的位元據傳輸:不知道是大尾端還是小尾端的話,解析時肯定是錯啊!
  • 反編譯器中的整數資料:指令倒無所謂什麼順序,但指令後面跟著的運算元要是不知道順序那可就亂套了!例如反編譯出程式中的一句:01 05 64 94 04 08。其中01 05表示add %eax寄存器,那麼後面運算元64 94 04 08的位元組序就至關重要了。小尾端的話,它就表示0x8049464,大尾端則完全相反。
  • 避開類型系統直接存取底層位元組:例如C語言中用cast將對象轉換成與其建立時完全不同的類型。應用編程當然不推薦這樣寫,但是在系統編程中這卻非常有用!
下面就再再溫習一下位元組序吧。假設地址0x100處存放了一個4位元組的整數0x01234567,即從地址0x100到0x103。那麼大小尾端的存放方式如所示。一定要注意的是:所謂大小都是相對記憶體位址來說的。大尾端就是從低地址到高地址,低地址存高位,高地址存低位,所以叫大尾端。 如果地址是從左向右增長的話,那麼大尾端就與我們習慣的書寫方式的順序相同。

但是,對於字串來說則不存在這種區分。例如字串"12345"的位元組為:31 32 33 34 35 00(終止符)。在任何使用ASCII作為字元編碼的機器上,不論位元組序、字長等環境如何,結果都是這樣。因為字串都是由一個個字元組成的,對於單個字元來說是不存在順序的。所以說, 字元資料比位元據具有更好的平台獨立性。
擴充一下:那用多位元組表示字元的Unicode編碼有沒有這種問題呢?“UTF-8以單位元組為編碼單元,沒有位元組序的問題。UTF-16以兩個位元組為編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每個編碼單元的位元組序。例如收到一個“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16位元組流“594E”,那麼這是“奎”還是“乙”?Unicode規範中推薦的標記位元組順序的方法是BOM,Byte Order Mark。BOM是一個有點小聰明的想法:在UCS編碼中有一個叫做”ZERO WIDTH NO-BREAK SPACE”的字元,它的編碼是FEFF。而FFFE在UCS中是不存在的字元,所以不應該出現在實際傳輸中。UCS規範建議我們在傳輸位元組流前,先傳輸字元”ZERO WIDTH NO-BREAK SPACE”。這樣 如果接收者收到FEFF,就表明這個位元組流是Big-Endian的;如果收到FFFE,就表明這個位元組流是Little-Endian的。因此字元”ZERO WIDTH NO-BREAK SPACE”又被稱作BOM。
關於尾端的典故也很有意思,摘抄一段放鬆一下:“Lilliput和Blefuscu這兩大強國在過去的三十六個月裡一直在苦戰。戰爭開始時由於一下原因:我們大家都認為,吃雞蛋前,原始的方法是打破雞蛋較大的一端,可是當今皇帝的祖父小時候吃雞蛋,一次按古法打雞蛋時碰巧將一個手指弄破了,因此他的父親,當時的皇帝,就下了一道赦令,命令全體臣民吃雞蛋是打破雞蛋較小的一端,違令者重罰。老百姓們對這項命令極為反感。曆史告訴我們,由此曾發生過六次叛亂,其中一個皇帝送了命,另一個丟了王位。這些判斷大多都是由Blefuscu的王國大臣們煽動起來的。叛亂平息後,流亡的人總是逃到那個帝國區尋求避難。據統計,先後幾次有一萬一千人情願受死也不肯去打破雞蛋較小的一端。關於這一爭端,曾出版過幾百本大部著作,不過大端派的書一直是受禁的,法律也規定該派的任何人不得做官。"(摘自蔣劍鋒譯的《格利佛遊記》第一卷第4章)Swift是在諷刺英國(Lilliput)和法國(Blefuscu)之間的持續的衝突。Danny Cohen,一位網路通訊協定的早期開創者,第一次使用這兩個術語來指代位元組順序。
2.4 Bit-level Operation & Logical Operation
香農建立了資訊理論,第一次在布爾代數和數字邏輯之間建立起了聯絡。我們可以將布爾運算擴充到位向量上,那麼位向量就有兩個很有用的方式:1)表示有限集合從而達到壓縮的目的。我可以這樣來編碼集合A {0, 1, ... w-1}的任意子集,用位向量[aw-1, ..., a1, a0]。當i屬於A時,將ai設為1。例如,我們用[01101001]表示[0, 3, 5, 6],用[01010101]表示[0, 2, 4, 6]。也就是說位向量是“倒著”儲存的!(待深入研究)
2)訊號掩碼。不同訊號能中斷程式的執行,所以我們可以用特定的位向量來啟用或禁用不同的訊號。
經典的位元運算:1) 清除值:x & 0xFF(只保留最低的一位元組)2) 設定值:x | 0x33) 可移植的“1”:~04) 反轉值:x ^ 0xF(異或的 特性1:101 ^ 111 = 010,而 特性2:101 ^ 000 = 101)5) 清零:XOR %edx, %edx (異或的 特性3。為什麼不直接設值,因為這種方式產生的機器碼只有兩位元組,而設值有五位元組)
邏輯運算與上面講過的位元運算經常是搞混。二者還是有很大的不同的:1)邏輯運算將任何非0參數看做TRUE,並且只返回1或者0。因此只有當參數是0和1時,邏輯運算才和位元運算有著相同行為。2)邏輯運算具有短路的效果。當某一部分邏輯運算後已經能確定整個運算式的真假時,後面部分的邏輯運算就不會執行了。這種行為也是位元運算所不具有的。
2.5 Integer Representation
對於不帶正負號的整數就非常簡單了,每一位都表示2的i次方就可以了。

對於有符號整數呢,先說一種我們直接能想到的,用二進位表示整數的方式:用最高位當符號位,0表示整數,1表示負數。但這種方式有個重要的 缺陷:整數0有正負兩種表示方式。現代電腦使用的都是另一種我們耳熟能詳的二進位表示方式:補碼(two‘s complement)!最高位是1時則最高位的值是其權值取負。所以 我們看彙編或機器碼時經常能看到0xFFFF...xx,就是因為最高位是權值的負數,所以要置很多個次高位為1來表示一個“小”負數。例如0xFFFFFEC8=-312。小尾端機器上也就是C8 FE FF FF。

六星經典CSAPP筆記(2)資訊的操作和表示

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.