如果只进行一位左移,您可以使用 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)来混洗 dwords 的想法与上述移动距离模 32 的方案。