深刻理解計算機系統(3.5)------特殊的算術操做指令

  在上一篇博客 算術和邏輯操做 咱們介紹了以下圖幾種經常使用的算術邏輯指令,可是你們發現沒,這幾種指令若是在 IA32 上只能操做32位寄存器,好比我用乘法指令IMUL得出的結果超過了32位,那就會產生結果溢出,那應該怎麼辦呢?html

  

 

一、特殊的算術操做指令指令

  

  如上圖,上面的幾個指令支持有符號和無符號的全64位乘積以及整數除法,可是須要注意的是,存儲結果的寄存器固定死了,是一對寄存器%edx(高32位)和%eax(低32位)組成的 64 位的四字。htm

 

二、imull 和 mull 指令

  對於 imull 指令,上一章咱們在講算術和邏輯操做指令的時候,講過這個指令,這是一個乘法指令,指令形式是 imull S D,這裏有兩個操做數,它將計算S和D的乘積並截斷爲雙字,而後存儲在D當中。因爲在截斷時,無符號以及有符號的二進制序列是同樣的,所以此處的乘法指令並不區分有符號和無符號。blog

  可是對於本章的 imull 指令,它和前面的所表示的乘法指令有所不一樣,這裏只有一個操做數,如上圖,它的指令形式是 imull S。可是實際上它還有一個默認的操做數——寄存器%eax,這二者相乘,最終的結果是將高32位存入%edx 寄存器,低 32 位存入%eax 寄存器。get

  若是咱們只取低 32 位的結果,那麼這裏指令的意思和上篇博客所講的乘法指令意思是同樣的了,imull S D,只不過這裏的D是寄存器 %eax。博客

  這裏咱們能夠看一個實例:imull $0x3,咱們假設此時%eax寄存器的值爲0x82345600。也就是咱們須要計算0x3*0x82345600的值,這裏直接給出二者相乘的16進製表示,爲0xFFFF FFFE 869D 0200。這個結果爲64位的,所以咱們寄存器的先後狀態以下所示。擴展

  本實例引用:http://www.cnblogs.com/zuoxiaolong/p/computer17.html引用

  

  能夠看到,%eax保存着低32位的結果,單說這32位的話,它的有符號數值爲-2036530688,正是咱們直接計算0x3*0x82345600的32位截斷後的有符號值,顯然這個結果溢出了。若是組合上高32位,則結果爲-6331497984,將它加上或者取模4294967296(2的32次方)將獲得咱們32位的結果。這裏的有符號乘法採起的是先符號擴展被乘數,而後二者相乘,將結果再截斷爲64位所得。二進制

  對於mull的單操做數指令來說,就比較簡單了,它採用的是無符號乘法,所以就和咱們平時的十進制乘法運算相似,只是一樣的,它也會將結果的高32位存入%edx,將低32位存入%eax。im

  因此雖然 imull 能夠用於兩種不一樣的乘法操做,可是彙編器可以經過計算操做數的數據,分辨出想用哪條指令。數據

三、cltd 指令

  這個指令就是簡單的將%eax寄存器的值符號擴展32位到%edx寄存器,也就是說,若是%eax寄存器的二進制序列的最高位爲0,則cltd指令將把%edx置爲32個0,相反,若是%eax寄存器的二進制序列最高位爲1,則cltd指令將會自從填充%edx寄存器爲32個1。

 

四、idivl、divl指令

  這兩個指令分別是有符號除法和無符號除法指令,有符號除法指令 idivl 將寄存器 %edx(高32位)和 %eax(低32位)中的64位數做爲被除數,而除數做爲指令的操做數給出。指令將商存儲在寄存器 %eax 中,將餘數存儲在寄存器 %edx 中。

  好比指令idivl $0x3的結果,咱們假設此時%eax寄存器的值爲0x82345600。也就是咱們須要計算0x82345600/0x3的值,這裏直接給出二者相除的16進製表示,商爲0xD6117200,餘數爲0x0。所以咱們寄存器的先後狀態以下所示。

  

  能夠看到,在idivl這個指令執行的過程當中,其實對被除數進行了符號擴展,相似於cltd指令,或者有時也會將%eax移動到%edx,而後對%edx進行算術右移31位的運算。這兩種方式的結果是同樣的,都是將%eax符號擴展32位並存儲在%edx當中。

相關文章
相關標籤/搜索