Иллюстрированный самоучитель по Assembler

Способы адресации

Регистровая косвенная адресация со смещением (базовая и индексная)

Адресуется память (байт или слово). Относительный адрес операнда определяется, как сумма содержимого регистра BX, BP, SI или DI и указанной в команде константы, иногда называемой смещением. Смещение может быть числом или адресом. Так же, как и в случае базовой адресации, при использовании регистров BX, SI и DI подразумевается сегмент, адресуемый через DS, а при использовании ВР подразумевается сегмент стека и, соответственно, регистр SS.

Рассмотрим применение косвенной адресации со смещением на примере прямого вывода в видеобуфер.

mov AX,0B800h;Сегментный адрес
mov ES,AX;видеобуфера в ES
mov DI, 80*2*24;Смещение к нижней строке экрана
mov byte ptr ES: [DI],'О';Символ на экран
mov byte ptr ES:2[DI],'К';Запишем символ в следующую позицию
mov byte ptr ES:4[DI],'! ';Запишем символ в следующую позицию

В этом примере в качестве базового выбран регистр DI; в него заносится базовый относительный адрес памяти, в данном случае смещение в видеобуфере к началу последней строки экрана. Модификация этого адреса с целью получить смещение по строке экрана осуществляется с помощью констант 2 и 4, которые при вычислении процессором исполнительного адреса прибавляются к содержимому базового регистра DI.

Иногда можно встретиться с альтернативными обозначениями того же способа адресации, которые допускает ассемблер. Вместо, например, 4[ВХ] можно с таким же успехом написать [ВХ+4], 4+[ВХ] или [ВХ]+4. Такая неоднозначность языка ничего, кроме путаницы, не приносит, однако ее надо иметь в виду, так как с этими обозначениями можно столкнуться, например, рассматривая текст деассемблированной программы.

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

;Основная программа
push DS;В стек загружаются значения
push ES;трех регистров,
push SI;передаваемых подпрограмме
call mysub;Вызов подпрограммы mysub,
;использующей эти параметры
;Подпрограмма mysub
mov BP,SP;Поместим в ВР текущий адрес вершины стека
mov АХ,2[ВР],;Читаем в АХ последний параметр (SI)
mov ВХ,4[ВР];Читаем в ВХ предыдущий параметр (ES)
mov CX,6[BP];Читаем в СХ первый параметр (DS)

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

Иллюстрированный самоучитель по Assembler › Основы программирования › Способы адресации
Рис. 2.15. Состояние стека после загрузки в него трех параметров и перехода на подпрограмму

Если бы подпрограмма просто сняла со стека находящиеся там параметры, она первым делом изъяла бы из стека адрес возврата, и лишила бы себя возможности вернуться в основную программу (подробнее вопросы вызова подпрограммы и возврата из нее будут обсуждаться в последующих разделах). Поэтому в данном случае вместо команд pop удобнее воспользоваться командами mov. Подпрограмма копирует в ВР содержимое трех параметров и перехода на мое SP и использует затем этот адрес в качестве базового, модифицируя его с помощью базовой адресации со смещением.

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

В нашем фрагментарном примере мы не рассматриваем вопрос возврата в основную программу. Вдумчивый читатель мог также усомниться в правильности или, лучше сказать, в разумности текста подпрограммы. Ведь перенося параметры из стека в регистры общего назначения, подпрограмма затирает их исходное содержимое. Если же они не содержали ничего нужного, то ими можно было воспользоваться для передачи параметров в подпрограмму, а не связываться с мало наглядными операциями со стеком. Действительно, ради краткости мы опустили операции, практически необходимые в любой подпрограмме – сохранение в стеке (опять в стеке!) тех регистров, которые будут использоваться в подпрограмме. Кстати, это относится и к регистру ВР. В реальной подпрограмме эти действия следовало выполнить, что привело бы к изменению смещений при регистре ВХ, которые приняли бы значения (с учетом сохранения 4 регистров) 10, 12 и 14.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.