Автоинкрементная и автодекрементная адресация
Иногда, адресация, при которой после каждого обращения по заданному адресу с использованием механизма косвенной адресации, значение адресной ячейки автоматически увеличивается на длину считываемого операнда, называется автоинкрементной. Адресация с автоматическим уменьшением значения адресной ячейки называется автодекрементной.
Регистровая адресация
Предполагается, что операнд находится во внутреннем регистре процессора.
Пример:
.text
main:
movl $0x12345, %eax /* записать в регистр константу 0x12345
*/
movl %eax, %ecx /* записать в регистр %ecx операнд,
который находится в регистре %eax */
Относительная адресация
Этот способ используется тогда, когда память логически разбивается на блоки, называемые сегментами. В этом случае адрес ячейки памяти содержит две составляющих: адрес начала сегмента (базовый адрес) и смещение адреса операнда в сегменте. Адрес операнда определяется как сумма базового адреса и смещения относительно этой базы:
Для задания базового адреса и смещения могут применяться ранее рассмотренные способы адресации. Как правило, базовый адрес находится в одном из регистров регистровой памяти, а смещение может быть задано в самой команде или регистре.
Рассмотрим два примера:
1. Адресное поле команды состоит из двух частей, в одной указывается номер регистра, хранящего базовое значение адреса (начальный адрес сегмента), а в другом адресном поле задается смещение, определяющее положение ячейки относительно начала сегмента. Именно такой способ представления адреса обычно и называют относительной адресацией.
2. Первая часть адресного поля команды также определяет номер базового регистра, а вторая содержит номер регистра, в котором находится смещение. Такой способ адресации чаще всего называют базово-индексным.
Главный недостаток относительной адресации - большое время вычисления физического адреса операнда. Но существенное преимущество этого способа адресации заключается в возможности создания "перемещаемых" программ - программ, которые можно размещать в различных частях памяти без изменения команд программы. То же относится к программам, обрабатывающим по единому алгоритму информацию, расположенную в различных областях ЗУ. В этих случаях достаточно изменить содержимое базового адреса начала команд программы или массива данных, а не модифицировать сами команды. По этой причине относительная адресация облегчает распределение памяти при составлении сложных программ и широко используется при автоматическом распределении памяти в мультипрограммных вычислительных системах.
Лекция 5: Команды ассемблера
Команда mov
Синтаксис:
mov источник, назначение
Команда mov производит копирование источника в назначение. Рассмотрим примеры:
/*
* Это просто примеры использования команды mov,
* ничего толкового этот код не делает
*/
.data
some_var:
.long 0x00000072
other_var:
.long 0x00000001, 0x00000002, 0x00000003
.text
.globl main
main:
movl $0x48, %eax /* поместить число 0x00000048 в %eax */
movl $some_var, %eax /* поместить в %eax значение метки
some_var, то есть адрес числа в
памяти; например, у автора
содержимое %eax равно 0x08049589 */
movl some_var, %eax /* обратиться к содержимому переменной;
в %eax теперь 0x00000072 */
movl other_var + 4, %eax /* other_var указывает на 0x00000001
размер одного значения типа long - 4
байта; значит, other_var + 4
указывает на 0x00000002;
в %eax теперь 0x00000002 */
movl $1, %ecx /* поместить число 1 в %ecx */
movl other_var(,%ecx,4), %eax /* поместить в %eax первый
(нумерация с нуля) элемент массива
other_var, пользуясь %ecx как
индексным регистром */
movl $other_var, %ebx /* поместить в %ebx адрес массива
other_var */
movl 4(%ebx), %eax /* обратиться по адресу %ebx + 4;
в %eax снова 0x00000002 */
movl $other_var + 4, %eax /* поместить в %eax адрес, по
которому расположен 0x00000002
(адрес массива плюс 4 байта --
пропустить нулевой элемент) */
movl $0x15, (%eax) /* записать по адресу "то, что записано
в %eax " число 0x00000015 */
Внимательно следите, когда вы загружаете адрес переменной, а когда обращаетесь к значению переменной по её адресу. Например:
movl other_var + 4, %eax /* забыли знак $, в результате в %eax
находится число 0x00000002 */
movl $0x15, (%eax) /* пытаемся записать по адресу
0x00000002 - > получаем segmentation
fault */
movl 0x48, %eax /* забыли $, и пытаемся обратиться по
адресу 0x00000048 - > segmentation
fault */
Команда lea
lea - мнемоническое от англ. Load Effective Address. Синтаксис:
lea источник, назначение
Команда lea помещает адрес источника в назначение. Источник должен находиться в памяти (не может быть непосредственным значением - константой или регистром). Например:
.data
some_var:
.long 0x00000072
.text
leal 0x32, %eax /* аналогично movl $0x32, %eax */
leal some_var, %eax /* аналогично movl $some_var, %eax */
leal $0x32, %eax /* вызовет ошибку при компиляции,
так как $0x32 - непосредственное
значение */
leal $some_var, %eax /* аналогично, ошибка компиляции:
$some_var - это непосредственное
значение, адрес */
leal 4(%esp), %eax /* поместить в %eax адрес предыдущего
элемента в стеке;
фактически, %eax = %esp + 4 */