访问程序集中的结构数组

时间:2014-11-03 21:29:32

标签: assembly x86 nasm

我有一个455字节的数组,包含13个,35字节的数据结构。

TurnTreeBuff:   resb 455    ; TurnNum (1 byte) + MT (16 bytes) + PM (16 bytes)
                ; + BoardState (2 bytes) = 35 bytes * 13 turns = 455 bytes

最初,我认为我可以通过获取索引,乘以35并将其添加到TurnTreeBuff来访问特定的数据结构。但唯一有效的比例因子是1,2,4和8.

所以这个:

mov word [TurnTreeBuff+ebx*35],ax ; doesn't work

我可以通过将索引复制到另一个寄存器,然后将原始索引值左移5次并将其复制到其移位值3次来实现。但这看起来真的很麻烦。使用MUL命令看起来也很麻烦。我最好只将结构填充为64字节,所以它是2的倍数?这似乎也很浪费。

有更好的方法吗?

(使用NASM 2.10汇编32位二进制文​​件)

1 个答案:

答案 0 :(得分:2)

* 35确实无法编译:

mov word [TurnTreeBuff+ebx*35],ax ; doesn't work

处理器仅支持2的幂,仅支持前几个:x1,x2,x4和x8。因此,如果您的结构较大,则必须恢复使用乘法。

请注意,mul / imul速度非常快(即与add或sub一样快),所以你不必担心使用它,尽管如果一个简单的移位适用于你的结构(即你提到的64字节) )那么使用班次可能要好得多。 (如果你在下一行使用结果,mul / imul需要更长的时间。)

最后,来自奇数地址的32位进程中的mov不是一个好主意。所以你的结构的大小至少应该是4个字节的倍数,所以在你的情况下是36个字节。

P.S。你也可以使用这两个功能:所以你的索引(ebx)可以设置为0,9,18等,然后在指令中使用x4。然而,在地址字段中使用乘数减慢了一点......但是,如果你想玩得开心,你可以做Jester提出的将裸指数(0,1,2等)乘以的东西。使用lea ecx, [ebx * 8 + ebx]乘以9,然后在另一个地址中使用x4。这么酷的事情的一大问题是:如果你的结构改变了它的大小......你必须重写很多代码

现在,假设您循环遍历结构数组,我通常会做的是将结构的大小添加到索引中。例如:

  mov ebx, TurnTreeBuff  ; get address of first structure
.L1:
  ...
  mov al, [ebx+0] ; TurnNum
  mov eax, [ebx+1] ; MT 1st work (should be aligned...)
  mov eax, [ebx+5] ; MT 2nd work
  ..
  mov ax, [ebx+33] ; BoardState
  ...
  add ebx, 35 ; again, use a multiple of your architecture: 16, 32, 64 bits...
  loop .L1

现在mov指令非常有效,因为你没有复杂的地址模式会减慢速度(假设你进行了数百万次访问,它会显示!)

请注意,应重新组织您的结构以使事情保持一致:

  TurnNum (1 byte)
  PAD (1 byte)
  BoardState (2 bytes)
  MT (16 bytes)
  PM (16 bytes)

否则你会一直在不对齐的位置击中记忆,这最终会减慢速度。

P.S。 x2,x4和x8主要添加到处理器中,因此可以访问指针数组,还可以访问这些大小的结构。它在指令中仅使用2位,因此限制范围:1 <&lt;&lt; n其中n为0,1,2,3。