简体   繁体   English

移位2个32位寄存器

[英]Shifts in 2 32-bit registers

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

This function rotates the current 64-bit mask (mask[]) by rotateCnt places. 此函数通过rotateCnt位置旋转当前的64位掩码(mask [])。 If the rotateCnt is positive, rotate left; 如果rotateCnt为正,则向左旋转; rotateCnt ,向左旋转。 if the rotateCnt is negative, rotate right. 如果rotateCnt为负,则向右旋转。 Only the lower 6 bits of the rotateCnt should be used for the rotateCnt . 只将rotateCnt的低6位用于rotateCnt

But I have to do the rotate, in 2 32-bit registers that simulates 1 64 bit register, logically performing 64 bit operations across two 32-bit registers. 但是我必须在2个32位寄存器中进行旋转,以模拟1个64位寄存器,在两个32位寄存器之间进行逻辑64位运算。 They told me to do 2 loops, but I can't figure this out? 他们告诉我做2次循环,但我无法弄清楚吗? Any h 任何时间

As you're using x86, take a look at shld and shrd . 在使用x86时,请看一下shld和shrd You won't need loops (why they asked for loops is beyond me). 您不需要循环(为什么他们要求循环超出了我的范围)。

Update 更新资料

Here's a DevStudio 2005 style function that uses inline assembler to do what you want. 这是一个DevStudio 2005样式函数,该函数使用内联汇编器执行所需的操作。 Do not present this as a solution without fully understanding how it all works (especially how the negative counts do a right rotate) because it will be incredibly easy for your teachers to spot that you copied this without knowing how it works (ie Teacher: "How does this work?", You: "Errr..." => FAIL). 在没有完全理解其工作原理(尤其是负数如何正确旋转)的情况下,请勿将其作为解决方案提出,因为您的老师非常容易发现您在不知道其工作原理的情况下复制了此内容(即教师:“这是如何工作的?”,您:“ 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
  }
}

There are probably quicker instructions for this, but here's the idea... If you're rotating left: 可能有更快的说明,但这是个主意...如果您向左旋转:

  1. take the most significant rotateCnt bits from the high-order register, shift them right 32-rotateCnt bits, and stash the result somewhere 从高阶寄存器中获取最高有效的rotateCnt位,将它们右移32-rotateCnt位,并将结果存储在某个位置

  2. shift the high-order register left by rotateCnt bits 将高位寄存器向左rotateCnt

  3. take the most significant rotateCnt bits from the low-order register, shift them left 32-rotateCnt bits, and add the result to the high-order register 从低位寄存器中取出最高有效的rotateCnt位,将它们左移32-rotateCnt位,然后将结果加到高位寄存器中

  4. shift the remaining bits in the low-order register left by rotateCnt bits and add the bits that you saved in step 1 将低位寄存器中的剩余位向左rotateCnt位,然后添加您在步骤1中保存的位

I'm sure you can see how to extend this process to any number of registers. 我确定您可以看到如何将此过程扩展到任意数量的寄存器。 If rotateCnt can be larger than 32 bits, you'll have to work a little harder, especially in the general case (n registers instead of just 2). 如果rotateCnt可以大于32位,则您将不得不付出更多的努力,尤其是在一般情况下(n个寄存器,而不是仅2个)。 One thing that may help is to notice that shifting left by n bits is the same as shifting right by (size-n) bits. 可能有帮助的一件事是,注意左移n位与右移(size-n)位相同。

From your comments, I see that you're supposed to use a loop. 从您的评论中,我看到您应该使用循环。 You can always apply the rotate procedure described above 1 bit at a time for rotateCnt iterations. 您始终可以一次对上述rotateCnt迭代一次应用上述旋转过程。 In that case, you'd obviously change rotateCnt in the description above to 1 . 在这种情况下,您显然rotateCnt上面描述中的rotateCnt更改为1

A single bit rotate is simply a single bit shift with carries out of one word being applied to the next word with a special case that a carry out of the high word gets applied to the low word. 单个旋转只是将一个字的进位应用于下一个字,而特殊情况是将高字的进位应用于低字。

It may help you to consider a picture of what needs to happen in certain scenarios. 它可以帮助您考虑某些情况下需要发生的情况。 I'll use 4-bit words below and I'll assume the rotate is to the left; 我将在下面使用4位字,并假设旋转是在左侧; the same concepts apply to whatever word size you might use: 相同的概念适用于您可能使用的任何字号:

// 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    

To use this basic operation to rotate multiple positions, just loop the appropriate number of times. 要使用此基本操作旋转多个位置,只需循环适当的次数即可。

Note that this can be done without any loops at all by applying the right set of bitmasks and shifts. 请注意,这可以通过应用正确的位掩码和移位集而完全没有任何循环。 Basically you can get all the bits that will carry out of a word in one shot without looping. 基本上,您可以一次性完成一个单词的所有操作,而无需循环。 A looping version is probably more straightforward to implement - you might consider doing that first and using it as a verification test if you decide to improve it to a non-looping version. 循环版本可能更容易实现-如果您决定将其改进为非循环版本,则可以考虑先将其用作验证测试。

think about how you would do this in C for example, then translate that to asm. 想想如何在C语言中执行此操作,然后将其转换为asm。

Using 32 bit variables to do a single bit shift left for example, assuming ra is the upper 32 bits and rb the lower 例如,使用32位变量向左移一位,假设ra为高32位,rb为低位

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

For a rotate you might do something along these lines 如果要轮换,您可以按照以下方式进行操作

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; }
}

You can then wrap a loop around one of those and do it N times. 然后,您可以将循环环绕其中之一,并进行N次。

Or say an 8 bit shift left 或者说左移8位

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

Or say an N bit shift left 或者说左移N位

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

Or an n bit rotate left (which is the same as a 32-n bit rotate right)(there is a reason why some processors only have a rotate right and the left is virtual or vice versa). 或向左旋转n位(与向右旋转32-n位相同)(这是某些处理器仅向右旋转而向左为虚拟或相反的原因)。

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

Then look at the instruction set and see what is available and matches what you are doing. 然后查看指令集,查看可用的内容并与您的操作匹配。

In short to shift bits you need to take the bit on one side and put it in the next bit. 简而言之,要移位钻头,您需要将钻头放在一侧,然后放在下一个钻头中。 If you align yourself on some boundary like a variable or register there is no difference you take the bit from one side and shift it into the other, it may take more code as the instruction set or programming language doesnt support it directly doesnt mean you cant do it. 如果您将自己对准某个边界(如变量或寄存器),则没有区别,您可以从一侧移到另一侧,这可能需要更多代码,因为指令集或编程语言不直接支持它并不意味着您不能做吧。 Just like you can perform a 2048 bit multiply on an 8 bit processor with no multiply instruction, just takes more code than other processors, but it is very doable. 就像您可以在没有乘法指令的8位处理器上执行2048位乘法一样,只需要比其他处理器更多的代码即可,但这是非常可行的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM