Search code examples
arraysassemblyx86y86

Accessing Elements of an Array inside of an Array - Y86 Assembly


I am wondering that in assembly (in my case Y86), is it possible to have an array inside of an array? And if it is, how would I access the elements inside of that array. I know you dereference arrays to get their elements, but that's only with one array in a stack. Is there a way to get an element inside of an array inside of an array.

Example because that's challenging to explain:

Normal grab of an element:

 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

Now say I have this:

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

 array2:
    .long array1

Am I able to access array2 element one and then access array1's elements?


Solution

  • The pushl %edx does not store the array to the stack, but the memory address of first element.

    In your other example the first element of array2 is 32 bit integer value, which is equal to memory address of array1, so in C language terms the array2 is array of pointers.

    When you fetch first element of array2 into some register, you have "pointer" (memory address) in it, and by fetching value from that address you will fetch first element of array1 (or you can modify it by some offset to fetch further elements).

    This "array of pointers to arrays" pattern is often used when you have several arrays of same/similar type with different lengths and you want to store them continuously in memory, for example:

    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
    

    Now if you want value "[2, 3]", i.e. the value "8", you can't simply multiply row value 2 by "column size" like in the matrix16x16 example, because rows don't have fixed length, so you will instead calculate offset into mainArray first, like (I will use x86 AT&T syntax, because I don't know Y86, but you should be able to get the idea, as they are basically the same instructions, just Y86 has more limited instruction set and you have more verbose and cryptic syntax with more prefix/suffix parts of instruction name):

    ; 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")
    

    Sorry for not using y86, but as I said, I don't know it... If you have hard time to decipher the x86 example, try to describe your difficulties in comment, I may try eventually to fix the syntax to y86, or maybe somebody else will suggest fixes...


    Am I able to access array2 element one and then access array1's elements?

    Yes, of course, those values are just ordinary 32 bit integers (memory addresses too, on your y86 platform), so you can of course fetch that address of sub-array from top array, and then fetch the value from that sub-array address to reach "value". Try to check in debugger, how the memory looks after defining your array, and how those values represent your original source code.

    The assembly is sort of so simple and trivial, that it is quite difficult/tedious to write complex abstractions in it, but as long as we are talking about single instruction or memory access, expect the thing to be super simple. If you see some complexity there, you are probably misunderstanding what is happening under the hood, it's all just 0/1 bit values, and moving them around a bit (usually in common quantities like 8, 16, 32 or 64, for other group of bits you need often several instructions to get the desired result, while these above are natively supported as byte/short/long/...). The complexity comes from the how-to-write-that-algorithm with simple copy/plus/minus instructions only.