Что такое mov в ассемблере

от admin

Что такое mov в ассемблере

Инструкция MOV помещает значение в регистр. Например, поместим значение 1 в регистр X0:

В качестве второго операнда инструкция принимает 16-битное значение. Такое значение еще называется immediate или непосредственный операнд . Для числа 1 требуется не больше 16 бит, поэтому проблем не возникнет. Но что если мы захотим поместить в регистр гораздо большее значение, например, 400000000, памятуя о том, что регистры у нас могут содержать 64-битные значения? При компиляции через GCC GNU мы получим ошибку:

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

Также с помочь инструкции MOV можно загружать значение из одного реггистра в другой:

В данном случае копируем содержимое регистра X2 в регистр X1.

Применение сдвига и вращения

При помещении значения в регистр команда mov позволяет сдвинуть его на определенное количество бит. Для сдвига и вращения значения применяются следующие операции:

LSL : логический сдвиг влево

LSR : логический сдвиг вправо

ASR : арифметический сдвиг вправо

ROR : поворот вправо

После команды идет непосредственный операнд, который указывает, на сколько бит надо сдвинуть значение. Например:

В данном случае кладем в регистр X1 значение 22, затем берем его, применяем сдвиг/поворот и кладем в регистр X2. Следует учитывать, что команда mov позволяет только применить сдвиг к значению из регистра.

Операции сдвига настолько распространены, что для них имеются псевдонимы:

Инструкция MOVK (move keep) представляет разновидность инструкции MOV и позволяет загрузить все 64 бита регистра. В реальности она загружает 16-битные операнды в одну из 4 частей регистра, не оказывая никакого влияния на другие 48 бит. Например, допустим, мы хотим загрузить в регистр X2 64-битное шестнадцатеричное значение 0x1234ABCD5F5F8D7E. В этом случае мы могли бы написать:

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

Следует отметить, что первый вызов инструкции mov в реальности эквивалентен инструкции MOVZ , которая аналогична MOVK за тем исключением, что заполняет оставшиеся 48 байт нулями.

Инструкция MOVN (Move Not) работает аналогично MOV за тем исключением, что она инвертирует все разряды числа при загрузке в регистр, то есть 1 изменяет на 0, а 0 — на 1. Эта инструкция ценна тем, что может применяться для получения отрицательного значения числа, ведь отрицательное значение по сути предполагает инвертирование разрядов и прибавление 1 к инвертированному числу. Что производительнее, чем использовать инструкцию умножения.

Кроме того, инструкция MOVN за счет дополнительного знакового бита (17 бит вместо 16 бит для mov) позволяет использовать значение в два раза больше. При этом если ассемблер видит, что указанное число превышает 16 бит, допустимых для инструкции MOV , то он автоматически преобразует инструкцию в MOVN . Например:

Здесь инструкция MOV преобразуется в MOVN, так как переданное значение

Применение инструкций MOV

Пример небольшой программы, которая использует различные инструкции MOV :

Description

The mov instruction is used to move data into registers or RAM. In other words, it is used to read and write into memory.

MOVSX (Move with sign extension) and MOVZX (Move with zero extension) are special versions of the mov instruction that perform sign extension or zero extension from the source to the destination. This is the only instruction that allows the source and destination to be different sizes. (And in fact, they must be different sizes).

MOVSXD: (MOVSXD r64, r/m32) Move doubleword to quadword with sign-extension.

MOV—Move

The moffs8, moffs16, moffs32 and moffs64 operands specify a simple offset relative to the segment base, where 8, 16, 32 and 64 refer to the size of the data. The address-size attribute of the instruction determines the size of the offset, either 16, 32 or 64 bits.

** In 32-bit mode, the assembler may insert the 16-bit operand-size prefix with this instruction (see the following “Description” sec-

tion for further information).

***In 64-bit mode, r/m8 can not be encoded to access the following byte registers if a REX prefix is used: AH, BH, CH, DH.

Instruction Operand Encoding

Op/En Operand 1 Operand 2 Operand 3 Operand 4
MR ModRM:r/m (w) ModRM:reg (r) NA NA
RM ModRM:reg (w) ModRM:r/m (r) NA NA
FD AL/AX/EAX/RAX Moffs NA NA
TD Moffs (w) AL/AX/EAX/RAX NA NA
OI opcode + rd (w) imm8/16/32/64 NA NA
MI ModRM:r/m (w) imm8/16/32/64 NA NA

Description

Copies the second operand (source operand) to the first operand (destination operand). The source operand can be an immediate value, general-purpose register, segment register, or memory location; the destination register can be a general-purpose register, segment register, or memory location. Both operands must be the same size, which can be a byte, a word, a doubleword, or a quadword.

The MOV instruction cannot be used to load the CS register. Attempting to do so results in an invalid opcode excep-tion (#UD). To load the CS register, use the far JMP, CALL, or RET instruction.

If the destination operand is a segment register (DS, ES, FS, GS, or SS), the source operand must be a valid segment selector. In protected mode, moving a segment selector into a segment register automatically causes the segment descriptor information associated with that segment selector to be loaded into the hidden (shadow) part of the segment register. While loading this information, the segment selector and segment descriptor information is validated (see the “Operation” algorithm below). The segment descriptor data is obtained from the GDT or LDT entry for the specified segment selector.

A NULL segment selector (values 0000-0003) can be loaded into the DS, ES, FS, and GS registers without causing a protection exception. However, any subsequent attempt to reference a segment whose corresponding segment register is loaded with a NULL value causes a general protection exception (#GP) and no memory reference occurs.

Loading the SS register with a MOV instruction inhibits all interrupts until after the execution of the next instruc-tion. This operation allows a stack pointer to be loaded into the ESP register with the next instruction (MOV ESP, stack-pointer value) before an interrupt occurs 1 . Be aware that the LSS instruction offers a more efficient method of loading the SS and ESP registers.

When operating in 32-bit mode and moving data between a segment register and a general-purpose register, the 32-bit IA-32 processors do not require the use of the 16-bit operand-size prefix (a byte with the value 66H) with

Читать:
Как из кельвинов перевести в цельсии

If a code instruction breakpoint (for debug) is placed on an instruction located immediately after a MOV SS instruction, the break-point may not be triggered. However, in a sequence of instructions that load the SS register, only the first instruction in the sequence is guaranteed to delay an interrupt.

In the following sequence, interrupts may be recognized before MOV ESP, EBP executes:

MOV SS, EDX MOV SS, EAX MOV ESP, EBP

this instruction, but most assemblers will insert it if the standard form of the instruction is used (for example, MOV DS, AX). The processor will execute this instruction correctly, but it will usually require an extra clock. With most assemblers, using the instruction form MOV DS, EAX will avoid this unneeded 66H prefix. When the processor executes the instruction with a 32-bit general-purpose register, it assumes that the 16 least-significant bits of the general-purpose register are the destination or source operand. If the register is a destination operand, the resulting value in the two high-order bytes of the register is implementation dependent. For the Pentium 4, Intel Xeon, and P6 family processors, the two high-order bytes are filled with zeros; for earlier 32-bit IA-32 processors, the two high order bytes are undefined.

In 64-bit mode, the instruction’s default operation size is 32 bits. Use of the REX.R prefix permits access to addi-tional registers (R8-R15). Use of the REX.W prefix promotes operation to 64 bits. See the summary chart at the beginning of this section for encoding data and limits.

Operation

Loading a segment register while in protected mode results in special checks and actions, as described in the following listing. These checks are performed on the segment selector and the segment descriptor to which it points.

Flags Affected

Protected Mode Exceptions

If attempt is made to load SS register with NULL segment selector.

If the destination operand is in a non-writable segment.

If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit.

If the DS, ES, FS, or GS register contains a NULL segment selector.

If segment selector index is outside descriptor table limits.

If the SS register is being loaded and the segment selector’s RPL and the segment descriptor’s DPL are not equal to the CPL.

If the SS register is being loaded and the segment pointed to is a non-writable data segment.

If the DS, ES, FS, or GS register is being loaded and the segment pointed to is not a data or readable code segment.

If the DS, ES, FS, or GS register is being loaded and the segment pointed to is a data or nonconforming code segment, but both the RPL and the CPL are greater than the DPL.

If attempt is made to load the CS register.

If the LOCK prefix is used.

Real-Address Mode Exceptions

If attempt is made to load the CS register.

If the LOCK prefix is used.

Virtual-8086 Mode Exceptions

If attempt is made to load the CS register.

If the LOCK prefix is used.

Compatibility Mode Exceptions

Same exceptions as in protected mode.

64-Bit Mode Exceptions

If the memory address is in a non-canonical form.

If an attempt is made to load SS register with NULL segment selector when CPL = 3.

If an attempt is made to load SS register with NULL segment selector when CPL < 3 and CPL

If segment selector index is outside descriptor table limits.

If the memory access to the descriptor table is non-canonical.

If the SS register is being loaded and the segment selector’s RPL and the segment descriptor’s DPL are not equal to the CPL.

If the SS register is being loaded and the segment pointed to is a nonwritable data segment.

If the DS, ES, FS, or GS register is being loaded and the segment pointed to is not a data or readable code segment.

If the DS, ES, FS, or GS register is being loaded and the segment pointed to is a data or nonconforming code segment, but both the RPL and the CPL are greater than the DPL.

Инструкция MOV

Пожалуй, инструкция MOV в ассемблере самая простая. Синтаксис этой команды такой:

MOV ПРИЁМНИК, ИСТОЧНИК

С помощью этой команды можно переместить значение из ИСТОЧНИКА в ПРИЁМНИК . То есть по сути команда MOV копирует содержимое ИСТОЧНИКА и помещает это содержимое в ПРИЁМНИК .

Никакие флаги при этом НЕ изменяются.

При использовании этой команды следует учитывать, что имеются некоторые ограничения. А именно, инструкция MOV не может:

  • Записывать данные в регистры CS и IP.
  • Копировать данные из одного сегментного регистра в другой сегментный регистр (сначала нужно скопировать данные в регистр общего назначения).
  • Копировать непосредственное значение в сегментный регистр (сначала нужно скопировать данные в регистр общего назначения).

ИСТОЧНИКОМ может быть один из следующих:

  • Область памяти (MEM)
  • Регистр общего назначения (REG)
  • Непосредственное значение (например, число) (IMM)
  • Сегментный регистр (SREG)

ПРИЁМНИКОМ может быть один из следующих:

  • Область памяти (MEM)
  • Регистр общего назначения (REG)
  • Сегментный регистр (SREG)

С учётом ограничений, которые были описаны выше, комбинации ПРИЁМНИК-ИСТОЧНИК могут быть следующими:

Пример использования инструкции MOV:

ПРИМЕЧАНИЕ
Этот пример не будет работать в Windows 2000 и выше, так как эти операционные системы запрещают программам напрямую обращаться к “железу”, а в этом примере мы пытаемся записать данные непосредственно в видеопамять.

Ну и напоследок скажу, почему эта инструкция называется MOV. Это сокращение от английского слова MOVE, которое можно перевести как “переместить, перенести, передвинуть”. И, как теперь вам уже понятно, эта команда соответствует своему названию — она перемещает значение из одного регистра в другой. Хотя с точки зрения русского языка это будет не совсем правильно, потому что перемещения не происходит — значение из ИСТОЧНИКА никуда не исчезает (не перемещается), по сути оно копируется и вставляется в ПРИЁМНИК.

Похожие статьи