
Рис. 1. Организация памяти в виде одномерного массива
Как отчетливо видно из рис. 1, адрес начального байта любого числа легко вычислить по формуле:
Ai = A0 + Di = A0 + 2i;
Обязательно обратите внимание на тот факт, что нумерацию в массиве удобно начинать с нуля: именно в этом случае расчетная формула выглядит наиболее просто. Простота объясняется тем, что фактически для адресации необходимого элемента приходится вычислять объем памяти, занятый всеми предшествующими ему элементами. Таким образом, например, пятому элементу удобнее всего ставить в соответствие номер 4, тогда первому, соответственно 0 (т.е. ему «ничего не предшествует»).
В языках программирования высокого уровня для удобства человека индексы часто все-таки начинают с единицы. В наиболее развитых версиях языка BASIC даже предусмотрен специальный оператор OPTION BASE, который позволяет устанавливать начальное значение индексов массива 0 или 1 (по умолчанию всегда действует 0). В случае, когда индексы начинаются не с 0, а с 1, при вычислении смещения Di следует вместо переменной i написать i–1.
Мы в нашем сегодняшнем эксперименте ради простоты реализации везде будем начинать отсчет индексов с нуля.
Итак, пусть в памяти, начиная с адреса 200h, располагается массив из 9 двухбайтовых целых чисел, который изображен на рис. 1. Значения чисел, разумеется, можно было задать произвольно, но для удобства проверки правильности работы программ мы занесем в элементы массива их индексы от 0 до 8.
Поставим задачу найти в массиве и извлечь в регистр AX пятый элемент (на рис. 1 он обведен пунктиром; как вы, конечно, поняли из предыдущих рассуждений, этот элемент имеет номер 4).
Для доступа к элементам массива в процессорах фирмы Intel предусмотрен большой ассортимент методов адресации. Доступ к массивам основывается на двух методах – базовом и индексном, остальные являются их модификациями. Пока познакомимся с индексным способом адресации.
Для хранения индексов в рассматриваемом семействе процессоров предусмотрены специальные индексные регистры SI и DI. Хранящееся в любом из них значение индекса может автоматически складываться с начальным адресом массива, который должен быть указан явным образом в виде константы. Запись 200[SI], например, означает, что при обращении к памяти будет выбран адрес, равный сумме начального адреса массива 200 и индексного смещения, находящегося в данный момент в регистре SI. Подчеркнем, что величина смещения не есть значение индекса: в нашем примере она вдвое превышает последнее, поскольку каждое число занимает 2 байта. Вместо умножения на 2 хорошие программисты, как правило, используют сдвиг на один бит влево; в частности, в нашей программе второй командой стоит SHL SI,1, что как раз и обеспечивает требуемый сдвиг влево (по-английски SHift Left).
Примечание. Сдвиг влево формально эквивалентен приписыванию после числа дополнительного нуля. В повседневной десятичной системе это приводит к увеличению значения в 10 раз (из 12 получается 120!), а в двоичной, соответственно, вдвое.
Приведенного объяснения вполне достаточно чтобы понять работу нашей несложной программы, которая состоит из трех машинных инструкций и описывается в протоколе 3.
Протокол 3
-a |
При разборе протокола 2 непременно обратите внимание на следующие детали (соответствующие места в тексте, как обычно, подчеркнуты).
Вот мы и научились пользоваться индексной адресацией.
Пример: найти в массиве и извлечь в регистр AX пятый элемент в соответствии с вариантом (см.таблица1).
Таблица 1