Доступ к элементам массива внутри массива - сборка Y86

Мне интересно, что в сборке (в моем случае 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?

1 ответ

Решение

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", вы не можете просто умножить значение строки 2 на "размер столбца", как в примере matrix16x16, потому что строки не имеют фиксированной длины, поэтому вместо этого вы будете вычислять смещение в 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, для другой группы). битов часто требуется несколько инструкций, чтобы получить желаемый результат, в то время как эти выше изначально поддерживаются как byte/short/long/...). Сложность возникает из-за того, как написать этот алгоритм с простыми инструкциями копирования / плюс / минус.

Другие вопросы по тегам