2017-07-20 36 views
3

在瀏覽通過一些內核代碼,我發現對於存儲器對準的公式作爲公式存儲器alignement

對準=((操作數+(取向 - 1))&〜(取向 - 1))

所以後來我甚至寫一個程序是:

#include <stdio.h> 

int main(int argc, char** argv) { 
    long long operand; 
    long long alignment; 
    if(argv[1]) { 
     operand = atol(argv[1]); 
    } else { 
     printf("Enter value to be aligned!\n"); 
     return -1; 
    } 
    if(argv[2]) { 
     alignment = strtol(argv[2],NULL,16); 
    } else { 
     printf("\nDefaulting to 1MB alignment\n"); 
     alignment = 0x100000; 
    } 
    long long aligned = ((operand + (alignment - 1)) & ~(alignment - 1)); 
    printf("Aligned memory is: 0x%.8llx [Hex] <--> %lld\n",aligned,aligned); 
    return 0; 
} 

但我沒有得到這個邏輯可言。這個怎麼用 ?

+0

用*二進制*表示將它寫出紙面。未對齊值和對齊值。在紙上*逐個執行操作*以查看錶達式每個部分的結果,並將它們拼湊在一起。當然,所有的二進制值都完成了。 –

+0

只是爲了精確,必須澄清的是,對齊邊界**必須是2 **的冪。 –

回答

1

基本上,該公式將整數operand(地址)增加到與alignment對齊的下一個地址。

表達

aligned = ((operand + (alignment - 1)) & ~(alignment - 1)) 

基本相同作爲位更容易理解式:

aligned = int((operand + (alignment - 1))/alignment) * alignment 

例如,具有操作數(地址)102和對準10,我們得到:

aligned = int((102 + 9)/10) * 10 
aligned = int(111/10) * 10 
aligned = 11 * 10 
aligned = 110 

首先我們添加到地址9並得到111。然後,由於我們的對齊是10,所以我們基本上將最後一位數字清零,即111/10 * 10 = 110

請注意,對於每個10對齊的功率(即10,100,1000等),我們基本上清零了最後的數字。

在大多數的CPU,除法和乘法操作比位操作更多的時間,讓我們回到原來的公式:

aligned = ((operand + (alignment - 1)) & ~(alignment - 1)) 

公式的第二部分,使得只有當對準感2.例如功率:

... & ~(2 - 1) will zero last bit of address. 
... & ~(64 - 1) will zero last 5 bits of address. 
etc 

就像使用歸零的地址的10條路線功率的最後幾個數字,我們歸零最後幾位爲2個比對能力。

希望它現在對你有意義。

+0

感謝您的解釋。得到了最後的零位調零部分,但第一部分呢?正如我所建議的那樣,我確實在紙上嘗試了這一點,而且我發現這是有效的。但我仍然無法得知這是如何工作的。 – Zoso

+0

明白了。非常有意義。 – Zoso