Инструкция MOV помещает значение в регистр. Например, поместим значение 1 в регистр X0:
mov X0, #1
В качестве второго операнда инструкция принимает 16-битное значение. Такое значение еще называется immediate или непосредственный операнд . Для числа 1 требуется не больше 16 бит, поэтому проблем не возникнет. Но что если мы захотим поместить в регистр гораздо большее значение, например, 400000000, памятуя о том, что регистры у нас могут содержать 64-битные значения? При компиляции через GCC GNU мы получим ошибку:
Error: immediate cannot be moved by a single instruction
Чтобы загрузить значения гораздо большей разрядности нам может помочь инструкция MOVK , которая рассматривается далее.
Также с помочь инструкции MOV можно загружать значение из одного реггистра в другой:
MOV X1, X2
В данном случае копируем содержимое регистра X2 в регистр X1.
Применение сдвига и вращения
При помещении значения в регистр команда mov позволяет сдвинуть его на определенное количество бит. Для сдвига и вращения значения применяются следующие операции:
Язык ассемблера для Intel x86 — Урок #3 — Регистры, команда mov, способы адресации, арифметика
- LSL : логический сдвиг влево
- LSR : логический сдвиг вправо
- ASR : арифметический сдвиг вправо
- ROR : поворот вправо
После команды идет непосредственный операнд, который указывает, на сколько бит надо сдвинуть значение. Например:
mov X1, #22 mov X2, X1, LSL #1 // логический сдвиг влево на 1 разряд mov X2, X1, LSR #1 // логический сдвиг вправо на 1 разряд mov X2, X1, ASR #1 // арифметический сдвиг вправо на 1 разряд mov X2, X1, ROR #1 // поворот вправо на 1 разряд
В данном случае кладем в регистр X1 значение 22, затем берем его, применяем сдвиг/поворот и кладем в регистр X2. Следует учитывать, что команда mov позволяет только применить сдвиг к значению из регистра.
Операции сдвига настолько распространены, что для них имеются псевдонимы:
mov X1, #22 LSL X2, X1, #1 // логический сдвиг влево на 1 разряд LSR X2, X1, #1 // логический сдвиг вправо на 1 разряд ASR X2, X1, #1 // арифметический сдвиг вправо на 1 разряд ROR X2, X1, #1 // поворот вправо на 1 разряд
MOVK
Инструкция MOVK (move keep) представляет разновидность инструкции MOV и позволяет загрузить все 64 бита регистра. В реальности она загружает 16-битные операнды в одну из 4 частей регистра, не оказывая никакого влияния на другие 48 бит. Например, допустим, мы хотим загрузить в регистр X2 64-битное шестнадцатеричное значение 0x1234ABCD5F5F8D7E. В этом случае мы могли бы написать:
MOV X2, #0x8D7E MOVK X2, #0x5F5F, LSL #16 MOVK X2, #0xABCD, LSL #32 MOVK X2, #0x1234, LSL #48
Команда MOVK для заполнения нужной части регистра выполняет сдвиг на определенное количество бит, которое должно быть кратно 16.
Следует отметить, что первый вызов инструкции mov в реальности эквивалентен инструкции MOVZ , которая аналогична MOVK за тем исключением, что заполняет оставшиеся 48 байт нулями.
MOVN
Инструкция MOVN (Move Not) работает аналогично MOV за тем исключением, что она инвертирует все разряды числа при загрузке в регистр, то есть 1 изменяет на 0, а 0 — на 1. Эта инструкция ценна тем, что может применяться для получения отрицательного значения числа, ведь отрицательное значение по сути предполагает инвертирование разрядов и прибавление 1 к инвертированному числу. Что производительнее, чем использовать инструкцию умножения.
Assembler. Команды mov, add, sub, div, mul [#3]
Кроме того, инструкция MOVN за счет дополнительного знакового бита (17 бит вместо 16 бит для mov) позволяет использовать значение в два раза больше. При этом если ассемблер видит, что указанное число превышает 16 бит, допустимых для инструкции MOV , то он автоматически преобразует инструкцию в MOVN . Например:
MOV W1, #0xFFFFFFFE // (-2)
Здесь инструкция MOV преобразуется в MOVN, так как переданное значение
Применение инструкций MOV
Пример небольшой программы, которая использует различные инструкции MOV :
// Пример применения инструкций MOV .global _start // адрес входной точки в программу // Загружаем в регистр X2 значение 0x1234ABCD5678EF1A _start: MOV X2, #0xEF1A MOVK X2, #0x5678, LSL #16 MOVK X2, #0xABCD, LSL #32 MOVK X2, #0x1234, LSL #48 // Перемещаем значение регистра W2 в W1 (32-х битные регистры) MOV W1, W2 // пример операций сдвига и вращения MOV X1, X2, LSL #1 // Логический сдвиг влево на 1 бит MOV X1, X2, LSR #1 // Логический сдвиг вправо на 1 бит MOV X1, X2, ASR #1 // Арифметический сдвиг вправо на 1 бит MOV X1, X2, ROR #1 // Поворот вправо на 1 бит // те же инструкции только с использованием мнемоник LSL X1, X2, #1 // Логический сдвиг влево на 1 бит LSR X1, X2, #1 // Логический сдвиг вправо на 1 бит ASR X1, X2, #1 // Арифметический сдвиг вправо на 1 бит ROR X1, X2, #1 // Поворот вправо на 1 бит // пример инструкции MOVN MOVN X3, #45 // устанавливаем параметры и вызываем системный вызов Linux для выхода из программв MOV X0, #0 // 0 — код возврата MOV X8, #93 // номер функции Linux для выхода из программы — 93 SVC 0 // Вызываем функцию и выходим из программы
Источник: metanit.com
Лабораторная работа № 5. Командный цикл процессора
Даны три массива чисел. Требуется вычислить среднее арифметическое их максимальных элементов. Каждый массив задается двумя параметрами: адресом первого элемента и длиной.
Очевидно, в программе трижды необходимо выполнить поиск максимального элемента массива, поэтому следует написать соответствующую подпрограмму.
Параметры в подпрограмму будем передавать через регистры: R1 — начальный адрес массива, R2 — длина массива.
Рассмотрим конкретную реализацию этой задачи. Пусть первый массив начинается с адреса 085 и имеет длину 14 элементов, второй — 100 и 4, третий — 110 и 9. Программа будет состоять из основной части и подпрограммы. Основная программа задает параметры подпрограмме, вызывает ее и сохраняет результаты работы подпрограммы в рабочих ячейках.
Затем осуществляет вычисление среднего арифметического и выводит результат на устройство вывода. В качестве рабочих ячеек используются регистры общего назначения R6 и R7 — для хранения максимальных элементов массивов. Подпрограмма получает параметры через регистры R1 (начальный адрес массива) и R2 (длина массива).
Эти регистры используются подпрограммой в качестве регистра текущего адреса и счетчика цикла соответственно. Кроме того, R3 используется для хранения текущего максимума, а R4 — для временного хранения текущего элемента. Подпрограмма возвращает результат через аккумулятор. В табл. 9.9 приведен текст основной программы и подпрограммы.
Обратите внимание, цикл в подпрограмме организован с помощью команды jrnz, а модификация текущего адреса — средствами постинкрементной адресации.
Таблица 9.9. Программа примера 4
| Команда | Примечания |
| Основная программа | |
| RD #85 | Загрузка |
| WR R1 | параметров |
| RD #14 | первого |
| WR R2 | массива |
| CALL M | Вызов подпрограммы |
| WR R6 | Сохранение результата |
| RD #100 | Загрузка |
| WR R1 | параметров |
| RD #4 | второго |
| WR R2 | массива |
Таблица 9.9 (окончание)
Составить и отладить программу учебной ЭВМ для решения следующей задачи. Три массива в памяти заданы начальными адресами и длинами. Вычислить и вывести на устройство вывода среднее арифметическое параметров этих массивов. Параметры определяются заданием к предыдущей лабораторной работе (см. табл.
9.8), причем соответствие между номерами вариантов заданий 3 и 4 устанавливается по табл. 9.10.
Таблица 9.10. Соответствие между номерами заданий
| Номер варианта задания 4 |
| Номер строки в табл. 9.9 |
1. Формулировка варианта задания.
2. Граф-схема алгоритма основной программы.
3. Граф-схема алгоритма подпрограммы.
4. Распределение памяти (размещение в ОЗУ переменных, программы и необходимых констант).
5. Тексты программы и подпрограммы.
6. Значения исходных данных и результата выполнения программы.
1. Как работает команда mov R3, R7?
2. Какие действия выполняет процессор при реализации команды call?
3. Как поведет себя программа примера 4, если в ней вместо команд call m использовать команды jmp m?
4. После начальной установки процессора (сигнал Сброс) указатель стека SP устанавливается в 000. По какому адресу будет производиться запись в стек первый раз, если не загружать SP командой wrsp?
5. Как, используя механизмы постинкрементной и преддекрементнои адресации, организовать дополнительный стек в произвольной области памяти, не связанный с SP7
Реализация программы в ЭВМ сводится к последовательному выполнению команд. Каждая команда, в свою очередь, выполняется как последовательность микрокоманд, реализующих элементарные действия над операционными элементами процессора.
В программной модели учебной ЭВМ предусмотрен Режим микрокоманд, в котором действие командного цикла реализуется и отображается на уровне микрокоманд. Список микрокоманд текущей команды выводится в специальном окне Микрокомандный уровень (см. рис, 8.8).
Источник: studopedia.su
Инструкция MOV
Пожалуй, инструкция MOV в ассемблере самая простая. Синтаксис этой команды такой:
MOV ПРИЁМНИК, ИСТОЧНИК
С помощью этой команды можно переместить значение из ИСТОЧНИКА в ПРИЁМНИК . То есть по сути команда MOV копирует содержимое ИСТОЧНИКА и помещает это содержимое в ПРИЁМНИК .
Никакие флаги при этом НЕ изменяются.
При использовании этой команды следует учитывать, что имеются некоторые ограничения. А именно, инструкция MOV не может:
- Записывать данные в регистры CS и IP.
- Копировать данные из одного сегментного регистра в другой сегментный регистр (сначала нужно скопировать данные в регистр общего назначения).
- Копировать непосредственное значение в сегментный регистр (сначала нужно скопировать данные в регистр общего назначения).
ИСТОЧНИКОМ может быть один из следующих:
- Область памяти (MEM)
- Регистр общего назначения (REG)
- Непосредственное значение (например, число) (IMM)
- Сегментный регистр (SREG)
ПРИЁМНИКОМ может быть один из следующих:
- Область памяти (MEM)
- Регистр общего назначения (REG)
- Сегментный регистр (SREG)
С учётом ограничений, которые были описаны выше, комбинации ПРИЁМНИК-ИСТОЧНИК могут быть следующими:
REG, MEM SREG, MEM MEM, REG REG, REG SREG, REG MEM, IMM REG, IMM MEM, SREG REG, SREG
Пример использования инструкции MOV:
MOV AX, 0B800h ; установить AX = B800h (память VGA). MOV DS, AX ; копировать значение из AX в DS. MOV CL, ‘A’ ; CL = 41h (ASCII-код). MOV CH, 01001110b ; CH = атрибуты цвета (желтый текст на красном фоне). MOV BX, 72eh ; BX = позиция на экране = 2*(x + y*80).
MOV [BX], CX ; [0B800h:015Eh] = CX.
ПРИМЕЧАНИЕ
Этот пример не будет работать в Windows 2000 и выше, так как эти операционные системы запрещают программам напрямую обращаться к “железу”, а в этом примере мы пытаемся записать данные непосредственно в видеопамять.
Ну и напоследок скажу, почему эта инструкция называется MOV. Это сокращение от английского слова MOVE, которое можно перевести как “переместить, перенести, передвинуть”. И, как теперь вам уже понятно, эта команда соответствует своему названию — она перемещает значение из одного регистра в другой. Хотя с точки зрения русского языка это будет не совсем правильно, потому что перемещения не происходит — значение из ИСТОЧНИКА никуда не исчезает (не перемещается), по сути оно копируется и вставляется в ПРИЁМНИК.
Источник: av-assembler.ru