Мнемокод mov

Варианты использования команды mov:


mov eax, ebx
mov eax, 5

Первый вариант копирует содержимое одного регистра в другой регистр, тогда как второй вариант заносит в регистр некое число, заданное непосредственно в самой команде (в данно случае число 5). На этом примере наглядно видно, что операнды бывают разных видов. Если в роли операнда выступает название регистра, то говорят о регистровом операнде; если же значение указано прямо в самой команде, такой операнд называется непосредственным операндом.

На самом деле, в рассматриваемом случае следует говорить даже не о различных типах операндов, а о двух разных командах, которые просто обозначаются одинаковой мнемоникой. Две команды mov из нашего примера переводятся в совершенно разные машинные коды, причём первая из них занимает в памяти два байта, а вторая - пять, четыре из которых тратятся на расмещение непосредственного операнда.

Кроме непосредственных и регистровых операндов, существует ещё и третий вид операнда - адресный операнд, называемый также операндом типа память. В этом случае оператор задаёт (тем или иным способом) адрес ячейки или область памяти, с которой надлежит произвести заданное командой действие. Необходимо помнить, что в языке ассемблера NASM операнд типа "память" абсолютно всегда обозначается квадратными скобками, в которых пишется собственно адрес. В простейшем случае адрес задаётся в явном виде, то есть в форме числа; обычнопри программировании на языке ассемблера вместо чисел мы, как уже говорилось, используем метки. Например мы можем написать:


section .data
; ...
count   dd 0

(символ ";" задаёт в языке ассемблера комментарий), описав область памяти размером в 4 байт, с адресом которой связана метка count, и в которой исходно хранится число 0. Если теперь написать:


section .text

move [count], eax

эта команда mov будет обозначать копирование данных из регистра EAX в область памяти, помеченную меткой count, а, напрмер, команда:


mov edx, [count]

будет, наоборот, обозначать копирование из памяти по адресу count в регистр EDX.

Чтобы понять, зачем нужны квадратные скобки, рассмотрим команду:


mov edx, count

Вспомним, что метку (в данном случае count), как мы уже говорили, ассемблер просто заменяет на некоторое число, в данном случае - адрес области памяти. Например, если область памяти count расположена в ячейках, адреса которых начинаются с 40f2a008, то вышеприведённая команда - это абсолютно то же самое, как если бы мы написали:


mov edx, 40f2a008h

Теперь очевидно, что это просто уже знакомая нам форма команды mov с непосредственным операндом, т.е. эта команда заносит в регистр EDX число 40f2a008, не вникая в то, является ли это число адресом какой-либо ячейки памяти или нет. Если же мы добавим квадратные скобки, речь пойдёт уже оо обращении к памяти по заданному адресу, т.е. число будет использовано как адрес области памяти, где размещено значение, с которым надо работать (в данном случае поместить в регистр EDX).

Синтаксис At&T

direct addressing mode

movl ADDRESS, %eax

indexed addressing mode

movl string_start(,%ecx,1), %eax

register addressing mode (режим адресации регистра)

Копировать содержимое регистра EAX в регистр EBX

movl %eax %ebx

indirect addressing mode (режим косвенной адресации)

Если регистр содержит не значение, а адрес в памяти, по котоому находится значение, то копировать содержимое ячейки памяти, ссылка на которую находится в EAX в регистр EBX нужно так:

movl (%eax) %ebx

base pointer addressing mode (режим адресации базового указателя)

movl 4(%eax) %ebx

immediate mode (немедленный режим)

Поместить десятичное число 7 в регистр EBX

movl $7 %ebx

Формат ссылки на адрес в памяти

ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)

Конечный адрес рассчитывается по формуле
FINAL_ADDRESS = ADDRESS_OR_OFFSET + %BASE_OR_OFFSET + %INDEX * MULTIPLIER