你真的深刻理解計算機系統了嗎之篇章三:程序的結構

  計算機中的信息=位+上下文。進一步,信息能夠分爲兩大類:一類是數據,一類是指令。指令用來代表操做的動做,數據用來代表被操做的對象,這二者同時也構成了一個完整的程序。算法

  對於數據而言,咱們先來談整數的表示和運算。無符號編碼表示無符號數,補碼錶示有符號數,相信你們對這兩種編碼應該是很是熟悉的(無符號編碼沒有符號位,補碼的最高位表示符號位)。函數

  在整數的運算方面一共有兩種,一種是算術運算,一種是邏輯運算。算術運算就指日常的加減乘數,固然要注意溢出、符號位等各類狀況(這個講起來的話太多了,並且我也擔憂本身講很差,不懂的讀者能夠去翻翻書)。邏輯運算主要包括移位操做、或與非等,對於移位操做,必定要注意是算術右移仍是邏輯右移,算法右移在所缺的位置要補齊符號位,邏輯右移要補齊零。編碼

  因爲浮點型的表示和運算,我也掌握的不是太好,讀者本身翻書吧。翻譯

  對於指令而言,有傳送指令、算術指令、邏輯指令、跳轉指令以及支持過程調用和返回的指令。這些指令與c語言中的結構都是對應的,下面我會爲你們講解。指針

  傳送指令主要是mov a, b這種形式,像c語言中的賦值操做以及取某個變量的值等最後都會轉化爲這種指令。傳送指令一共有三種尋址方式。第一種方式爲當即數尋址,形式爲mov $imm, EM,表示將imm傳送到寄存器或者存儲器EM中;第二種方式爲寄存器尋址,形式爲mov Ea, EM,表示將寄存器Ea中的值傳送到EM中;第三種爲存儲器尋址,形式爲mov (Ea), EM,表示將寄存器中的值所表示的存儲器位置的值傳送到EM中,固然這個有不少變形,但本質是同樣的。要注意到不能從存儲器傳送到存儲器。對象

  在算術和邏輯指令中,像加減乘除、或與非、移位操做自沒必要說,在c語言中的這些操做與彙編中基本是沒什麼區別。我主要來講一下lea,即加載有效地址指令,它是mov指令的變形。指令形式爲lea S, D,效果是將S的地址傳送到D中,其中D必須爲寄存器,像c語言中的求地址操做&就對應這種彙編語言。例如lea (Ea), Eb,在mov指令中表示將寄存器中的值所表示的存儲器位置的值傳送到Eb中,而在lea指令中表示將寄存器Ea中的值傳送到寄存器Eb中。同時還能夠用這個指令來進行一些算術運算。it

  跳轉指令主要包括無條件跳轉和有條件跳轉,無條件跳轉的形式爲jmp Label或者jmp *Operand,後者的跳轉目標是從寄存器或者存儲器中讀出的。對於有條件跳轉,只有在符合某些條件的狀況下才會跳轉,好比je、jne等,那麼在彙編中是如何知道這些條件成立不成立呢?除了整數寄存器,CPU還包含一組單個位的條件碼寄存器,好比CF(無符號溢出)、ZF(零)、SF(負數)、OF(有符號溢出),它們描述的是最近操做的屬性,也有一些指令專門用來設置條件碼而不修改其餘寄存器,像test、cmp。跳轉指令根據這些條件碼的組合狀況來決定是否跳轉。在c語言中像if語言、for語言、while語言、switch語言最終都會翻譯成跳轉指令。test

  最後一種指令就是支持過程調用和返回的指令。其中call指令用來過程調用,ret指令用來從過程調用中返回。c語言中的過程最後會翻譯爲彙編中的過程調用代碼。在x86系統中一共有8個整數寄存器,其中有兩個寄存器支持過程的實現,分別是棧指針%esp,幀指針%ebp。當執行call Label時(Label表示被調用的標記,也能夠是*Operand的形式),計算機將返回地址(調用者的下一條指令地址)入棧,再將幀指針中保存的值(調用者的幀指針)入棧,最後將棧指針中保存的值傳給幀指針,下面就開始執行被調用者中的指令,當執行ret返回時就是call指令的逆序,先將幀指針中保存的值傳給棧指針,再push %ebp,將返回地址更新到程序計數器中,繼續調用函數的執行。變量

相關文章
相關標籤/搜索