計算機的算數運算 知識梳理


一、概要

揭示實數的表示方法、算術的算法、實現這些算法的硬件以及如何在指令中表示相關的內容。以及如何使用該計數加速算術運算密集型程序的運行

二、加法和減法

加減法:數據從右向左逐位相加,同時進位也相應的向左傳播,減法可通過將減數在簡單的取反之后再進行加法操作,通過加法來實現。

例:7-6,可直接通過原碼的減法進行操作,或者通過7加上-6的二進制補碼來實現

7-6=[0000 0111]原-[0000 0110]原=[0000 0001]原=1
7+(-6)=[0000 0111]原+[1111 1010]補=[0000 0001]=1

溢出:

硬件規模有限,若字寬只有32位,運算結果超出32位就會溢出。

二進制補碼操作的溢出:對加法,正數和負數相加時,和必然小於任意一個操作數的絕對值,不會溢出。做減法時,源操作數符號相同,不會發生溢出。加或減兩個32位的數可能產生需要33位來表示的結果,溢出發生時符號位被數值位占用而產生錯位。當兩個正數相加結果為負,即計算過程中發生了向符號位的進位操作,說明發生了溢出,反之亦然。減法時:當一個正數減去一個負數得到一個負的結果,或一個負數減去一個正數得到一個正的結果,也意味着發生了借位占用了符號位,即溢出。

無符號整數:無符號數通常表述內存地址,這種情況下的溢出可以忽略。

MIPS采用兩種類型的指令來處理哪些情況下忽略溢出,哪些情況下進行溢出的檢測的問題:

  • 加法add,立即數加法addi,減法sub,這三條指令在溢出時產生異常
  • 無符號加法addu,立即數無符號加法addiu,無符號減法subu,三條指令在發生溢出時不會產生異常

三、乘法

第一個操作源為被乘數multiplicand,第二個操作源被稱為乘數multiplier,最終的結果被稱為積product。若忽略符號位,乘積等於兩個操作數的位數之和,顯然要處理溢出。乘法的基本原則:當乘數位為1 時,只需將被乘數復制到合適的位置,當為0時,將0放到合適的位置。

乘法硬件只是簡單的移位和加法疊加。編譯器甚至會用移位指令來代替乘數為2的冪次的乘法操作。通過使用更多硬件的方法、並行做加法操作來提高運算速度。

順序的乘法算法和硬件

乘數被放置在32位乘數寄存器中,積初始化為0被放到64位的積寄存器中。被乘數在每步需要左移一位,因為它需要與前面的中間結果相加。32步之后,32位的被乘數將左移32位,所以需要用64位的寄存器存放被乘數,且初始化時被放到最低的32位上,最半部分初始化為0。每執行一步這個寄存器就左移一步,將被乘數與64位積寄存器中的中間結果對齊並累加到中間結果。步驟如下

  • 給乘積加上被乘數,將結果寫入乘積寄存器,乘數的最低位決定被乘數是否被加到積寄存器上
  • 被乘數寄存器左移一位,即將被乘數左移
  • 乘數寄存器右移一位,給出了下一個迭代要用的乘數位

上面3個步驟重復執行32次獲得積,若每步需一個時鍾周期,完成兩個32位數的相乘約需100個時鍾周期;一般加減法出現的次數比乘法頻繁5-100倍,所以多步乘法不會顯著影響性能,但若一個慢速操作在程序中占據一定比重,也會限制程序的性能。

改進——並行化加速執行:

  • 當乘數位為1時,將乘數和被乘數進行移位,同時將被乘數和積相加。
  • 這時需保證:硬件測試的是乘數最右邊的位,而且得到的是被乘數移位前的值。
  • 加法器和寄存器中有未使用的部分,可通過將加法器和寄存器的位長減半來進一步優化這個硬件結構
  • 當乘數為常數時,乘法也可用移位來替代,有短常數的乘法可替換為一系列的移位和加法,左移一位就是將一個數放大兩倍,幾乎每個編譯器都將以2為底的指數乘法替換為移位來進行優化

有符號乘法

首先將乘數和被乘數都轉化為正數,並記住原來的符號位,即可用上述最后的算法迭代31次,符號位不必參與運算,當符號不同時,積為負,對應符號位初始化為負。這里是使用32位數字來表示通常要處理的無限數字,移位步驟需要對有符號的乘積進行擴展。

更快速的乘法——摩爾定律

在乘法運算開始的時候通過檢查乘數的32位,來判斷被乘數是否被加上。即,為乘數的每一位提供一個32位的加法器,一個用來輸入被乘數和一乘數位相與的結果,另一個是上一個加法器的輸出。將每一個右邊的加法器的輸出作為左邊加法器的輸入,形成一個高32的加法器棧,將32個加法器組織成一個並行樹,只需等待log2(32),即5次32位加法的時間,而不是32次加法的時間。另外,通過使用進位保留加法器,乘法的計算速度可以快於5次加法,易於應用於流水線設計執行,且可以同步支持多個乘法運算。

MIPS中的乘法

MIPS提供一對單獨的32位寄存器來容納64位的積,稱為Hi和Lo.乘法mult和multu分別對應於有符號積和無符號積。需使用mflo(move from lo)指令來獲取32位的整數積,MIPS匯編器為乘法生成了一條偽指令,使用三個通用的寄存器,用mflo和mfhi指令將積送入指定的寄存器。

MIPS乘法指令都忽略溢出,所以要由軟件來檢測是否因積過大而32位不夠表示。對於multu指令,若Hi為0則無溢出(無符號乘積,高位為0);對於multi指令,若Hi為Lo的符號位則也無溢出(有符號位,最高位與未擴展部分相同)。可以使用指令mfhi(move from hi)將Hi的值移入一個通用寄存器來檢測溢出。

四、除法

兩個源操作數:被除數dividend和除數divisor,結果稱為商quotient,第二結果稱為余數remainder;被除數=商*除數+余數≡被除數/除數=商+余數;其中余數要小於除數。有時,使用除法僅僅是為了獲得余數,而忽視商,即求余運算。

除法算法及其硬件結構

這里假設被除數和除數都為正,則商和余數也都為非負,除法的源操作數和兩個結果都為32為寬,暫且忽略符號位。開始時,32位的商寄存器被設為0,將除數放置在64位除數寄存器的左半邊,算法每次迭代將除數向右移一位,每次右移一位和被除數對齊。余數寄存器也是64位寬,被初始化為被除數。控制邏輯決定何時對除數和商寄存器進行移位以及何時將新值寫入余數寄存器。具體步驟:

  • 從余數寄存器中減去除數寄存器中的內容,將結果放在余數寄存器中
  • 若結果為正,即,除數小於被除數,取商為1,即商寄存器左移,最低位設置為1
  • 若結果為負,則通過給余數寄存器加上除數寄存器的內容來恢復原值,結果放在余數寄存器,商同樣左移,最低位設為0
  • 除數右移,再次迭代,重復33次
  • 迭代完成后,余數和商存放在以他們命名的寄存器中

檢驗余數的正負只需簡單檢測余數的符號位是0還是1即可,這個算法需要n+1步來獲得適當的商和余數。通過將源操作數和商移位與減法同時進行來加速。寄存器和加法器有未用的部分,可勇敢將加法器和寄存器的位長減半來改進硬件結構。

改進版:只有余數寄存器是64位,除數寄存器和ALU位寬減半,余數進行左移。這個結構將商寄存器和余數寄存器的右半部分進行了拼接,余數是65位從而保證加法器的進位不會丟失。

有符號的除法

記住除數和被除數的符號,若兩者符號相異,則商為負。設置余數的符號必須滿足:被除數=除數*商+余數,若-(x/y)≠(-x)/y編程會面臨更大的挑戰,若不管除數和商和符號,保持被除數和余數的符號相同,就可以避免這種問題。所以,有符號除法算法在源操作數的符號相反時商為負,同時應使非零余數的符號和被除數的符號相同。

更快速的除法——摩爾定律

除法每次迭代前需要知道減法結果的符號,而乘法卻可以立刻生成32個部分積,所以不可像乘法一樣使用許多加速器來加速除法。但有一些計數如SRT的除法算法可以每步生成不止一個商位,通過查找表的方法來猜測每步幾個商位,查找表基於被除數和余數的高位部分來進行,它依賴后面的部分來修正錯誤的猜測。

MIPS中的除法

除法和乘法有相同的硬件執行順序。MIPS用32位的Hi和32位的Lo寄存器來處理乘法和除法。除法指令執行后,Hi存放余數,Lo存放商。有符號整數采用div,無符號整數采用divu,MIPS允許用三個寄存器采用mflo和mfhi將運算結果放入指定的通用寄存器中。MIPS處理除法指令忽略溢出,需要軟件檢驗商是否溢出。除法還可能產生除數為0這樣的錯誤運算,一些計算機會分辨這兩種異常。MIPS需通過軟件來判斷檢查除數是否發生此類錯誤。或者,在余數為負時,不需要立即將除數加回去,只是在下一步簡單的講除數加到移位后的余數上:(a+b)*2-b=a*2+b*2-b=a*2+b;前面的算法為恢復(restoring)算法,這里為不執行算法nonperforming,平均減少了三分之一的算術操作。

 


免責聲明!

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



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