0

我想知道在汇编中(在我的情况下为 Y86),是否可以在数组中包含一个数组?如果是,我将如何访问该数组中的元素。我知道您取消引用数组以获取它们的元素,但这只是堆栈中的一个数组。有没有办法在数组内获取数组内的元素。

示例,因为这很难解释:

正常抓取元素:

 array1:
    .long 0x0
    .long 0x0
    .long 0x0
    .long 0x0

 Main:  
   pushl %ebp 
   rrmovl %esp,%ebp
   irmovl array1,%edx       #store array1 on the stack
   pushl %edx
   mrmovl (%edx), %eax      #get the first element of array1
   rrmovl %ebp, %esp
   popl %ebp
   ret

现在说我有这个:

 array1:
    .long 0x0
    .long 0x0
    .long 0x0
    .long 0x0

 array2:
    .long array1

我可以访问 array2 元素一个然后访问 array1 的元素吗?

4

1 回答 1

3

pushl %edx不将数组存储到堆栈中,而是存储第一个元素的内存地址。

在您的另一个示例中, 的第一个元素array2是 32 位整数值,它等于 的内存地址array1,因此在 C 语言中array2是指针数组。

当您将第一个元素获取array2到某个寄存器中时,其中有“指针”(内存地址),并且通过从该地址获取值,您将获取的第一个元素array1(或者您可以通过一些偏移量对其进行修改以获取更多元素)。

当您有多个具有不同长度的相同/相似类型的数组并且您希望将它们连续存储在内存中时,通常会使用这种“指向数组的指针数组”模式,例如:

array0:
  .long 1, 2, 3
array1:
  .long 4
array2:
  .long 5, 6, 7, 8
array3:
  .long 9, 10
; notice the values in memory form a continuous block of 10 long values,
; so you can also access them through "array0" as single array of 10 values

mainArray:
  .long array0, array1, array2, array3

现在,如果您想要值“[2, 3]”,即值“8”,您不能像 matrix16x16 示例中那样简单地将行值 2 乘以“列大小”,因为行没有固定长度,所以您将改为mainArray首先计算偏移量,例如(我将使用 x86 AT&T 语法,因为我不知道 Y86,但您应该能够理解,因为它们基本上是相同的指令,只是 Y86 的指令集更有限并且您有更多冗长和神秘的语法以及指令名称的更多前缀/后缀部分):

; edi = 2 (row), esi = 3 (column)
movl   mainArray(, %edi, 4), %ebx  ; ebx = mainArray[2] (*4 because pointers are 32 bit)
  ; (in x86 AT&T syntax the target memory address is "edi*4 + mainArray")
  ; here ebx = array2 (and "array2" is symbolic name for memory address value)
  ; it is NOT whole array in single register, just the memory address of first element
movl   (%ebx, %esi, 4), %eax       ; eax = 8 (array2[3]) (again *4 because longs are used)
  ; (the target memory address is "ebx + esi*4")

很抱歉没有使用 y86,但正如我所说,我不知道...如果您很难破译 x86 示例,请尝试在评论中描述您的困难,我最终可能会尝试将语法修复为 y86,或者也许其他人会建议修复...


我可以访问 array2 元素一个然后访问 array1 的元素吗?

是的,当然,这些值只是普通的 32 位整数(在您的 y86 平台上也是内存地址),因此您当然可以从顶部数组中获取子数组的地址,然后从该子数组中获取值达到“价值”的地址。尝试检查调试器,定义数组后内存的外观,以及这些值如何代表您的原始源代码。

程序集非常简单和琐碎,在其中编写复杂的抽象是相当困难/乏味的,但只要我们谈论的是单指令或内存访问,就希望事情变得超级简单。如果您在那里看到一些复杂性,您可能误解了幕后发生的事情,这只是 0/1 位值,并且将它们移动一点(对于其他组,通常以 8、16、32 或 64 等常见数量您通常需要几条指令才能获得所需的结果,而上面的这些在本机上被支持为字节/短/长/...)。复杂性来自仅使用简单的复制/加/减指令的如何编写该算法。

于 2018-08-03T06:58:19.300 回答