如何在NASM Assembly中对大量字节进行一点移位?

时间:2013-11-12 11:39:50

标签: assembly x86 nasm

假设我在.data中定义了X个字节数:

db 00000000b,00100011b,11100011b,...........

假设我定义了50个字节。

我想抓住这50个字节,然后向左移动一下。上面的例子如下所示:

db 00000000b,01000111b,11000110b,...........

当我们使用4个字节时,这很容易,因为你只需将它们放入EAX并进行转换。但现在我有50个字节。

我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:2)

将任意数量的字节向左移一位:第一个SHL最低有效字节为一位。然后RCL所有其他字节一位,从第二个最不重要到最重要。

答案 1 :(得分:0)

如果只进行一位左移,可以使用rcl指令将一个存储字向左移一位,捕获进位,然后重复上一个字。您想要重置第一次迭代的进位。 (我很确定这不是NASM语法,但这不应该打扰你。)

   mov   esi, offset data_buffer
   mov   ebx, data_buffer_dword_count
   lea   esi, [esi+4*ebx-4]
   clc
loop:
   rcl   [esi]
   lea   esi, -4[esi]
   dec   ebx             ; this kind of loop is why dec instructions don't affect carry!
   jne   loop

如果将N> 1位移位,则这很慢。在这种情况下,请使用shift-left-double指令。该指令使用两个寄存器,并将该对移位指定距离(cl或某些直接常数)。您需要跟踪部分移位的结果;簿记有点棘手。

如果你的移位距离是31位或更少,这段代码应该这样做: (编辑:我用以前不那么笨重的东西替换了我之前的代码):

   mov   esi, offset data_buffer
   mov   ebx, data_buffer_dword_count
   lea   esi, [esi+4*ebx-4]
   xor   edi, edi        ; bits from last time; this acts like "clc" in above loop
loop:
   mov   eax, [esi]
   xor   edx, edx        ; make 64 bit value of next dword
   mov   ecx, shift_left_distance
   shld  edx, eax, cl    ; shift left across <edx,eax>
   add   eax, edi        ; form full shifted dword by combining with last partial 
   mov   [esi], eax      ; update storage with shifted result
   mov   edi, edx        ; save shifted but unstored bits from this round
   lea   esi, -4[esi]
   dec   ebx
   jne   loop

如果你想移动超过31位,那么你已经通过使用存储器偏移(dwords中的移位距离除以32)与上述移位距离模32的方案结合了改组dword的思想。

答案 2 :(得分:0)

通常,有一种移位的风格在进位中移位或通过进位。进位位用于从一个换档操作中移出并使用它来移入下一个换档操作。所以如果向左移动你将从lsbyte开始,它的msbit移出,然后移到lsbyte的下一个右边,依此类推,在所有字节上创建一个级联效果。我会留给读者查看班次操作,看看哪些做了什么。记住您需要控制移位的第一个移位操作,因此清除进位或使用不同的指令。通常通过进位的转换称为旋转。

答案 3 :(得分:0)

使用add + adc序列可以最好地将一位字节数移一位 - 您可以组合任意长度的操作,例如:

lea edi, [array]
mov eax, [edi]
mov bx,  [edi + 4]
mov cl,  [edi + 6]

add eax, eax        ;; shift the MSB to Carry bit
adc bx, bx          ;; shift the previous carry to bit 0 + produce new carry
adc cl, cl

mov [edi], eax      ;; write back
mov [edi + 4], bx
mov [edi + 6], cl