我们正在学习有限的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的幂)的有效方法,因此通常在编写汇编时使用。将值左移1等于将值乘以2(21 == 2)。将值左移2等于将值乘以4(22 == 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。

关于assembly - 为什么SHL在8086中“移动” 2个字节?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59331718/

10-11 16:02