2014-11-03 5 views
1

У меня есть массив размером 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-битный двоичный)

+0

Является ли проблема с частотой, проблемой является память? Или проблема в читаемости кода? –

+0

Нет. Я только что закончил читать язык сборки. Шаг за шагом: Программирование с помощью Linux, и я пытаюсь применить небольшое приложение для практики. Он работает на моем рабочем столе, поэтому на самом деле нет ограничений на скорость, использование памяти и т. Д. Я бы хотел, чтобы он был читабельным, без расточительности. Прагматичная средняя почва. – Legion

+1

32-битный двоичный файл. Я думаю, вы используете 32-битный код. Вы считали «imul»? –

ответ

2

Это * 35 бы действительно не компилируется:

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

процессор поддерживает только мощность двух и только первые несколько: x1, x2 , x4 и x8. Поэтому, если ваша структура больше, вам нужно вернуться к использованию умножения.

Обратите внимание, что mul/imul очень быстрые (т.е. такие же быстрые, как добавление или под), поэтому вам не стоит беспокоиться об использовании таких, хотя если бы простой сдвиг работал с вашей структурой (то есть 64 байта, как вы упомянули) то использование сдвига, вероятно, намного лучше. (mul/imul занимает больше времени, если вы используете результат на самой следующей строке.)

Наконец, mov в 32-битном процессе с нечетным адресом - это не очень хорошая идея. Таким образом, размер вашей структуры должен быть, по крайней мере, кратным 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 < < n где n равно 0, 1, 2, 3.

+0

Некоторые моменты: + mul/imul ** не ** так быстро, как добавление или вспомогательный источник: (http://www.agner.org/optimize/instruction_tables.pdf) + Процессоры обычно имеют выделенное оборудование для генерации адресов. Таким образом, использование добавлений или полномочий в 2 умножения не замедляет работу вообще на процессорах x86. –

+0

Адресация не может замедлить работу новых версий x86. Хотя, если вы злоупотребляете им, вы получаете большую программу, которая не так хорошо вписывается в кеш команд, создавая еще один вид замедления ... Для 'IMUL' с немедленным значением 2 цикла вместо 1 для 'ADD'. Я думаю, что это терпимо. Плюс, если у вас могут быть другие инструкции между ними до использования результата «IMUL», трубопровод, вероятно, «отменит» «потеря». –

Смежные вопросы