Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основы программирования на Ассемблере. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
11.08.2026
Размер:
607 Кб
Скачать

Косвенная регистровая адресация

Исполнительный адрес операнда содержится в базовом регистре ВХ, регистре указателя базы ВР или в индексном регистре (SI или DI). Операнды заключаются в квадратные скобки.

При использовании BX,SI или DI в качестве сегментного регистра подразумевается регистр DS.

При употреблении BP подразумевается регистр SS. (При использовании регистров ВХ или ВР адресацию называют базовой, при использовании регистров SI или DI – индексной.)

Применяется при многократном обращении к ячейке памяти.

MOV AX, [BX] загружает в АХ содержимое ячейки памяти, адресуемое значением регистра ВХ.

Чтобы поместить смещение адреса в регистр ВХ, можно применить операцию offset (смещение) к адресу ячейки памяти. Например, для загрузки слова из TABLE в регистр АХ можно воспользоваться последовательностью команд

MOV BX, offset TABLE MOV AX, [BX]

Эти две команды выполняют те же действия, что и одна команда

MOV AX,TABLE

Для доступа к нескольким ячейкам с базового адреса лучше иметь исполнительный адрес в регистре, так как легче манипулировать им.

Адресация по базе

Исполнительный адрес вычисляется с помощью сложения значения сдвига с содержимым регистров ВХ или ВР.

MOV AX, [BХ] + 4 ; если начальный адрес записи в ВХ, то в АХ загрузятся пятый и шестой байты от начала записи.

Данная команда эквивалентна следующим командам:

MOV AX, 4[BХ] или MOV AX, [BХ + 4].

25

Рассмотрим теперь пример использования базовой адресации со смещением при обращении к стеку:

;Основная программа

push DS ;В стек загружаются значения push ES ;трех регистров,

push SI ;передаваемых подпрограмме

call mysub ;Вызов подпрограммы mysub, использующей эти параметры

;Подпрограмма mysub

mov BP, SP ; Поместим в ВР текущий адрес вершины стека mov АХ,2[ВР] ;Читаем в АХ последний параметр (SI)

mov ВХ,4[ВР] ;Читаем в ВХ предыдущий параметр (ES)

Здесь продемонстрирован классический прием чтения содержимого стека без извлечения из него этого содержимого. После того как основная программа сохранила в стеке три параметра, которые потребуются подпрограмме, командой call вызывается подпрограмма mysub. Эта команда сохраняет в стеке адрес возврата (адрес следующего за call предложения основной программы, т. е. смещает указатель стека еще на одно слово) и осуществляет переход на подпрограмму.

Прямая адресация с индексированием

Исполнительный адрес вычисляется как сумма значений сдвига и индексного регистра (DI или SI). Тип адресации удобен при работе с

таблицами, когда сдвиг указывает на начало таблицы, а индексный регистр – на ее элемент. Например, если TABLE – таблица байт, то последовательность команд

MOV DI, 2

MOV AL, TABLE[DI]

загрузит третий элемент таблицы TABLE в регистр AL.

Пример заполнения массива из 10 000 слов натуральным рядом чисел. Зарезервируем в сегменте данных место под этот массив, а в сегменте команд организуем цикл занесения в последовательные слова массива ряда нарастающих чисел. Воспользуемся новыми командами (inc, add и loop), которые в дальнейшем будут рассмотрены более подробно.

26

;Сегмент данных array dw 10000

;Сегмент команд

 

mov SI, 0

;Начальное значение индекса элемента

 

 

;в массиве

 

mov АХ, 0

;Первое число-заполнитель

 

mov СХ, 10000

;Число шагов в цикле (всегда в СХ)

fill:

mov array[SI], AX

;Занесение числа в элемент массива

 

inc AX

;Инкремент числа-заполнителя

 

add SI,2

;Смещение в массиве к следующему слову

 

loop fill

;Возврат на метку fill (СХ раз)

Цикл начинается с команды, помеченной меткой fill. В этой команде содержимое АХ, поначалу равное 0, переносится в ячейку памяти, адрес которой вычисляется, как сумма адреса массива array и содержимого индексного регистра SI, в котором в первом шаге цикла тоже 0. В результате в первое слово массива заносится 0. Далее содержимое регистра АХ увеличивается на 1, содержимое регистра SI – на 2 (из-за того, что массив состоит из слов), и командой loop осуществляется переход на метку fill, после чего тело цикла повторяется при новых значениях регистров АХ и SI. Число шагов в цикле, отсчитываемое командой loop, определяется исходным содержимым регистра СХ.

Адресация по базе с индексированием

Исполнительный адрес вычисляется, как сумма значений базового регистра, индексного регистра и, возможно, сдвига.

Относительный адрес операнда определяется, как сумма содержимого следующих пар регистров:

[ВХ] [SI] (подразумевается DS:[BX][SI])

[ВХ][DI] (подразумевается DS:[BX][DI])

[ВР] [SI] (подразумевается SS:[BP][SI])

[ВР] [DI] (подразумевается SS:[BP][DI])

Удобен при адресации двумерных массивов, когда базовый регистр содержит начальный адрес массива, а значения сдвига и индексного регистра есть смещения по строке и столбцу.

MOV AX, TABLE[BX][DX]

27

Возможна также следующая запись команд:

MOV AX, TABLE[BX + 2][DX]

MOV AX, TABLE[BX][DX + 2]

Пример заполнения массива из 10 000 слов натуральным рядом чисел с использованием базово-индексной адресации.

;Сегмент данных

 

array dw 10000

 

;Сегмент команд

 

 

mov BX, offset array

; Базовый адрес массива в базовом

 

 

; регистре

 

mov SI, 0

; Начальное значение индекса элемента

 

 

; в массиве

 

mov АХ, 0

; Первое число-заполнитель

 

mov CX,10000

; Число шагов в цикле

fill:

mov [BX][SI],AX

; Отправим число в массив

 

inc AX

; Инкремент числа-заполнителя

 

add SI, 2

; Смещение в массиве к следующему

 

 

; слову

 

loop fill

; На метку fill (CX раз)

Повышение эффективности достигается за счет того, что команда занесения числа в элемент массива оказывается короче (так как в нее не входит адрес массива) и выполняется быстрее, так как этот адрес не надо каждый раз считывать из памяти.

6. ЦИКЛЫ

Команда LOOP служит для выполнения конечного числа циклов, использует начальное значение в регистре CX. В каждом цикле команда LOOP автоматически уменьшает содержимое регистра CX на 1. Пока значение в CX не равно нулю, управление передается по адресу, указанному в операнде, и если в CX будет 0, управление переходит на следующую после LOOP команду.

28

Существует две разновидности команды LOOP

1.LOOPE (или LOOPZ).

2.LOOPNE (или LOOPNZ).

Обе команды также уменьшают значение регистра CX на 1. Команда LOOPE передает управление по адресу операнда, если регистр CX имеет ненулевое значение и флаг нуля установлен (ZF = 1).

Команда LOOPNE передает управление по адресу операнда, если регистр CX имеет ненулевое значение и флаг нуля сброшен (ZF = 0).

Пример программы обнуления массива из 1024 слов.

// сегмент данных

 

array

dw 1024 dup(?) //зарезервирован массив из 1024 слов

// сегмент кода

 

mov cx,1024

// инициализация счетчика

lea bx, array или (mov bx offset array) //адрес массива поместить в bx

mov si, 0

 

//обнулили указатель

mull: mov [bx] [si], 0

//очищаем содержимое элемента массива

inc si //увеличиваем индекс, чтобы он указывал на слово inc si //

loop mull //цикл на метку;

Стоит отметить некоторые детали, связанные с механизмом выполнения команды loop. При реализации этой команды процессор сначала уменьшает содержимое регистра СХ на единицу, а затем сравнивает полученное число с нулем. Если СХ > 0, переход на указанную метку выполняется. Если СХ = 0, цикл разрывается и процессор переходит на команду, следующую за командой loop. Поэтому после нормального выхода из цикла содержимое СХ всегда равно нулю. В коде команды loop под смещение к точке перехода отводится всего 1 байт. Поскольку смещение должно являться величиной со знаком, максимальное расстояние, на которое можно передать управление командой loop, составляет от –128 до + 127 байт. Тело цикла ограничивается всего 128 байтами. Если циклически повторяемый фрагмент программы имеет большую длину, цикл придется организовать, более сложным способом.

29

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]