为什么SHL在8086中“移动” 2个字节?

时间:2019-12-14 01:54:23

标签: assembly x86-16

我们正在学习有限的8086指令集。

当内存中有一个数组时,我们使用SHL在元素之间移动(取决于元素大小)。

例如,假设有一个2字节短裤的数组。该数组在ES段上,第一个元素从BX偏移量(ES:[BX])开始。

如果要转到下一个元素,请使用SHL BX,1,然后使用ES:[BX]进行访问。

ADD AX, ES:[BX]
SHL BX,1
ADD AX, ES:[BX]

我不明白为什么会这样,将偏移量乘以2。我们是否应该在BX上加2以转到下一个元素?

ADD AX, ES:[BX]
ADD BX,2
ADD AX, ES:[BX]

2 个答案:

答案 0 :(得分:2)

左移是执行二进制乘法(即乘以2的幂)的有效方法,因此通常在编写汇编时使用。将值左移1等于将值乘以2(2 1 == 2)。将值左移2等于将值乘以4(2 2 == 4)。依此类推,依此类推。

还有其他一些位操作技巧,可以有效地乘以2的非幂,但这里不再赘述,因为它们有些复杂。要查看它们,ask a C compiler

因此,您问题中的第一段代码不正确。您不想将指针乘以2。

正如您所说,访问数组中下一个值的方法是将指针增加元素的大小(以字节为单位)。对于WORD大小的数组,这意味着将指针增加2,就像您显示的那样,简单的ADD指令可以完成此操作:

ADD AX, ES:[BX]
ADD BX, 2
ADD AX, ES:[BX]

假设BX是指向数组的第一个元素的指针,该元素在ES段中分配,则将获取该元素的值并将其添加到AX中。然后,它将递增BX指向数组的第二个元素,并将该地址处的值添加到AX

在您可能更熟悉的C语言中,这等效于:

uint16_t* ptr    = ...;     // ES:[BX]
uint16_t  result = ...;     // AX

result += *ptr;
++ptr;
result += *ptr;

请注意,C会自动将指针增加其指向的值的大小。在这种情况下,由于ptr是指向uint16_t的指针,它将使地址增加2。

答案 1 :(得分:0)

是的,SHL指令对寄存器中的位进行移位。例如,00001111b变为00011110b。 SHR向右移动。 ROL和ROR旋转这些位。由于二进制是以2为基数,所以向左移位是每移位2乘以

另一个需要注意的是,如果要使用数组,每个条目都是连续的,那么我将看一下LODSW指令。