2

假设我在 中定义了.dataX 个字节:

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

假设我定义了 50 个字节。

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

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

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

我怎样才能做到这一点?

4

4 回答 4

2

将任意数量的字节左移一位:首先SHL是最低有效字节一位。然后RCL是所有其他字节一位,从第二个最低有效位到最高有效位。

于 2013-11-12T11:45:53.837 回答
0

通常有一种移位的味道,即移入或通过进位位。进位位用于从一个移位操作中取出移位,并使用它在下一个移位操作中移入。因此,如果向左移动,您将从 lsbyte 开始,它的 msbit 移出,并移入到 lsbyte 的下一个右侧,依此类推,在所有字节上产生级联效应。我将把它留给读者查找移位操作,看看哪些是做什么的。请记住您需要控制移入的第一个移位操作,因此清除进位位或使用不同的指令。通常通过进位进行的移位称为轮换。

于 2013-11-12T12:21:26.243 回答
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 的方案来组合 shuffle dwords 的想法。

于 2013-11-12T11:48:05.937 回答
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
于 2013-11-12T14:04:08.227 回答