【发布时间】:2023-12-29 03:26:01
【问题描述】:
我正在努力学习汇编语言。有人可以解释和/或举例说明如何使用寻址模式来访问以下每种数组类型中的元素吗?
DWORD数组结构数组,其中每个结构包含两个
DWORDs数组数组,其中每个数组有10个
DWORDs
【问题讨论】:
标签: arrays assembly x86 addressing-mode
我正在努力学习汇编语言。有人可以解释和/或举例说明如何使用寻址模式来访问以下每种数组类型中的元素吗?
DWORD数组
结构数组,其中每个结构包含两个DWORDs
数组数组,其中每个数组有10个DWORDs
【问题讨论】:
标签: arrays assembly x86 addressing-mode
您没有提及您具体针对的是哪个处理器,但在 386+ 中这会起作用。我没有 MASM,但 MASM 使用 Intel 语法。
假设ebx 是基址寄存器,esi 是元素的索引寄存器。标准 32 位寄存器(eax、ebx、ecx、edx、ebp、esi、edi)对此处使用的寻址模式有效。 esp 可以用作基址寄存器,但不能用作索引寄存器。索引寄存器的值可以选择用 2、4 或 8 进行缩放。在此示例中,我们可以为 dword 数组使用缩放因子 4(在 386 个合法缩放因子中为 1、2、4 和 8)。
将数组中的值读入eax:mov eax, [ebx+4*esi]
将eax 的值存储到数组中:mov [ebx+4*esi], eax
让我们保持ebx 作为基地址。对于每个结构由 2 个双字组成的结构数组,我们可以为 esi 使用比例因子 8。
将第一个双字的值读入eax:mov eax, [ebx+8*esi]
将 eax 的值存储到第一个 dword 中:mov [ebx+8*esi], eax
将第二个dword的值读入eax:mov eax, [ebx+8*esi+4]
将eax 的值存储到第二个dword 中:mov [ebx+8*esi+4], eax
如果索引不能被硬编码,您只需将 4 添加到 ebx(或用于存储基地址的任何寄存器)。如果你有硬编码的基地址,那么你可以使用例如。 esi 解决结构和例如。 ebx 来解决您想要的 dword。请注意,在 386+ 中,您不能在间接寻址中扩展多个寄存器(索引寄存器)。
我们仍然假设您事先不知道数组的基地址,您将在ebx 中拥有它,在esi 中拥有结构的索引,在edx 中拥有索引的双字。
要获取结构体的地址,可以使用lea 乘法优化(10 = 8 + 2):
编辑: 修正:lea esi,[4*esi](dword 为 4 个字节)
lea edi,[ebx+8*esi]
lea edi,[edi+2*esi]
现在您在edi 中获得了结构的地址。您只需将 dword 的索引(本例中存储在 edx 中)乘以 4(因为每个 dword 为 4 个字节)。
将dword的值读取到eax:mov eax,[edi+4*edx]。
将eax 的值存储到双字中:mov [edi+4*edx],eax。
【讨论】:
*10 的正常方式是*5*2,例如lea reg, [reg+reg*4]/add reg,reg。您可以通过将其设置为 *8 而不是 *2 来再扩展 4 个。所以对于案例 3:lea eax, [esi+esi*4]/lea eax, [ebx + esi*8](eax 保存内部数组/结构的地址)。然后mov eax, [eax + edx*4]。 (使用任何临时而不是 EAX,包括覆盖其中一个输入。)顺便说一句,shl esi, 2 会比 lea esi, [4*esi] 更有效,因为你不添加或复制。
逻辑很简单。
一维数组的第i个元素的地址就是数组(或第0个元素)的地址加上i * 元素大小.
如果你有一个二维数组,你可以把它当作一维数组的一维数组,并把它简化为我刚刚描述的已经很熟悉的情况:i的地址 em>- 2-dim 数组的第 1-dim 子数组就是 2-dim 数组的地址加上 i * 子数组大小。在第 i 个子数组中,我们已经知道如何计算第 j 个元素地址。
所以,二维数组的第(i,j)元素的地址就是数组的地址加上i * 子数组size + j * 元素大小 或者,等价地,数组的地址加上 (i * 元素个数在行中 + j) * 元素大小.
你应该能够弄清楚如何用汇编语言做到这一点。
【讨论】: