假设我在.data
中定义了X个字节数:
db 00000000b,00100011b,11100011b,...........
假设我定义了50个字节。
我想抓住这50个字节,然后向左移动一下。上面的例子如下所示:
db 00000000b,01000111b,11000110b,...........
当我们使用4个字节时,这很容易,因为你只需将它们放入EAX
并进行转换。但现在我有50个字节。
我怎样才能做到这一点?
答案 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