簡體   English   中英

移位2個32位寄存器

[英]Shifts in 2 32-bit registers

void rotate( unsigned long mask[], int rotateCnt ); 

此函數通過rotateCnt位置旋轉當前的64位掩碼(mask [])。 如果rotateCnt為正,則向左旋轉; rotateCnt ,向左旋轉。 如果rotateCnt為負,則向右旋轉。 只將rotateCnt的低6位用於rotateCnt

但是我必須在2個32位寄存器中進行旋轉,以模擬1個64位寄存器,在兩個32位寄存器之間進行邏輯64位運算。 他們告訴我做2次循環,但我無法弄清楚嗎? 任何時間

在使用x86時,請看一下shld和shrd 您不需要循環(為什么他們要求循環超出了我的范圍)。

更新資料

這是一個DevStudio 2005樣式函數,該函數使用內聯匯編器執行所需的操作。 在沒有完全理解其工作原理(尤其是負數如何正確旋轉)的情況下,請勿將其作為解決方案提出,因為您的老師非常容易發現您在不知道其工作原理的情況下復制了此內容(即教師:“這是如何工作的?”,您:“ Errr ...” =>失敗)。

void Rotate
(
  unsigned *value, // pointer to two 32bit integers
  int count        // number of bits to rotate: >= 0 left, < 0 = right
)
{
  __asm
  {
    mov esi,value
    mov eax,[esi]
    mov edx,[esi+4]
    mov ecx,count
    mov ebx,eax
    shld eax,edx,cl
    shld edx,ebx,cl
    test cl,32
    jz noswap
    xchg edx,eax
noswap:
    mov [esi],eax
    mov [esi+4],edx
  }
}

可能有更快的說明,但這是個主意...如果您向左旋轉:

  1. 從高階寄存器中獲取最高有效的rotateCnt位,將它們右移32-rotateCnt位,並將結果存儲在某個位置

  2. 將高位寄存器向左rotateCnt

  3. 從低位寄存器中取出最高有效的rotateCnt位,將它們左移32-rotateCnt位,然后將結果加到高位寄存器中

  4. 將低位寄存器中的剩余位向左rotateCnt位,然后添加您在步驟1中保存的位

我確定您可以看到如何將此過程擴展到任意數量的寄存器。 如果rotateCnt可以大於32位,則您將不得不付出更多的努力,尤其是在一般情況下(n個寄存器,而不是僅2個)。 可能有幫助的一件事是,注意左移n位與右移(size-n)位相同。

從您的評論中,我看到您應該使用循環。 您始終可以一次對上述rotateCnt迭代一次應用上述旋轉過程。 在這種情況下,您顯然rotateCnt上面描述中的rotateCnt更改為1

單個旋轉只是將一個字的進位應用於下一個字,而特殊情況是將高字的進位應用於低字。

它可以幫助您考慮某些情況下需要發生的情況。 我將在下面使用4位字,並假設旋轉是在左側; 相同的概念適用於您可能使用的任何字號:

// Note '-' in the carry column means "don't care"
//
// starting value (in binary):

              'high'             'low'
     carry     word     carry     word

        -     1 0 0 0     -     1 0 0 1

//  after shift left of each word:

        1     0 0 0 0      1    0 0 1 0

//  apply the carry out of the low word
//      to the high word:

        1     0 0 0 1      -    0 0 1 0    

//  apply the carry out of the high word
//      to the low word

        -     0 0 0 1      -    0 0 1 1    

要使用此基本操作旋轉多個位置,只需循環適當的次數即可。

請注意,這可以通過應用正確的位掩碼和移位集而完全沒有任何循環。 基本上,您可以一次性完成一個單詞的所有操作,而無需循環。 循環版本可能更容易實現-如果您決定將其改進為非循環版本,則可以考慮先將其用作驗證測試。

想想如何在C語言中執行此操作,然后將其轉換為asm。

例如,使用32位變量向左移一位,假設ra為高32位,rb為低位

if(rb&0x80000000) { ra<<=1; ra|=1; rb<<=1 }
else              { ra<<=1; rb<<=1; }

如果要輪換,您可以按照以下方式進行操作

if(rb&0x80000000)
{
  if(ra&0x80000000) { ra<<=1; ra|=1; rb<<=1: rb|=1; }
  else              { ra<<=1; ra|=1; rb<<=1; }
}
else
{
  if(ra&0x80000000) { ra<<=1; rb<<=1: rb|=1; }
  else              { ra<<=1; rb<<=1; }
}

然后,您可以將循環環繞其中之一,並進行N次。

或者說左移8位

ra=(ra<<8)|(rb>>(32-8));
rb<<=8;

或者說左移N位

ra=(ra<<=n)|(rb>>(32-n));
rb<<=n;

或向左旋轉n位(與向右旋轉32-n位相同)(這是某些處理器僅向右旋轉而向左為虛擬或相反的原因)。

temp=ra>>(32-n);
ra=(ra<<=n)|(rb>>(32-n));
rb=(rb<<<=n)|temp;

然后查看指令集,查看可用的內容並與您的操作匹配。

簡而言之,要移位鑽頭,您需要將鑽頭放在一側,然后放在下一個鑽頭中。 如果您將自己對准某個邊界(如變量或寄存器),則沒有區別,您可以從一側移到另一側,這可能需要更多代碼,因為指令集或編程語言不直接支持它並不意味着您不能做吧。 就像您可以在沒有乘法指令的8位處理器上執行2048位乘法一樣,只需要比其他處理器更多的代碼即可,但這是非常可行的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM