logo

Главная Система команд x86 Базовая система команд CPU IMUL

Система команд x86

Программирование - Архитектура и система команд микропроцессоров x86
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

IMUL

Знаковое умножение

Влияние команды на флаги и форматы команды:

OF

DF

IF

TF

SF

ZF

AF

PF

CF

*

     

?

?

?

?

*

 

Код

Команда

Описание

Проц.

Пример

F6 /5

IMUL r/m8

AX=AL*r/m8

8086

imul dl

F7 /5

IMUL r/m16

DX:AX=AX*r/m16

8086

imul si

F7 /5

IMUL r/m32

EDX:EAX=EAX*r/m32

Intel386

imul edi

0F AF /r

IMUL r16,r/m16

r16=r16*r/m16

Intel386

imul si,[di]

0F AF /r

IMUL r32,r/m32

r32=r32*r/m32

Intel386

imul edi,ecx

6B /r ib

IMUL r16,r/m16,imm8

r16=r/m16*(знакорасширенное imm8)

Intel186

imul ax,dx,4

6B /r ib

IMUL r32,r/m32,imm8

r32=r/m32*(знакорасширенное imm8)

Intel386

imul eax,edx,4

6B /r ib

IMUL r16,imm8

r16=r16*(знакорасширенное imm8)

Intel186

imul ax,4

6B /r ib

IMUL r32,imm8

r32=r32*(знакорасширенное imm8)

Intel386

imul edx,5

69 /r iw

IMUL r16,r/m16,imm16

r16=r/m16*(знакорасширенное imm16)

Intel186

imul ax,dx,1

69 /r id

IMUL r32,r/m32,imm16

r32=r/m32*(знакорасширенное imm16)

Intel386

imul eax,edx,8

69 /r iw

IMUL r16,imm16

r16=r16*imm16

Intel186

imul ax,8F57h

69 /r id

IMUL r32,imm32

r32=r32*imm32

Intel386

imul edx,9000

Описание:

Команда IMUL (Signed Multiply) относится к группе команд целочисленной (или двоичной) арифметики (Binary Arithmetic Instructions) и производит умножение двух знаковых целочисленных операндов (DEST и SRC). Существует три формы команды IMUL, которые отличаются прежде всего количеством явно задаваемых операндов.

Форма команды с одним операндом IMUL src в целом аналогична команде MUL. В этой форме операнд-назначение (DEST) задается неявно и является переменной в регистре (или регистровой паре) AX, DX:AX или EDX:EAX в зависимости от кода команды и атрибута размера операнда. Единственный операнд команды — операнд-источник (SRC) — может быть переменной в регистре или в памяти (r/m8, r/m16, r/m32). Команда перемножает содержимое аккумулятора (ALAX или EAX) и заданный операнд-источник (SRC) и помещает результат умножения в неявно заданный операнд-назначение (DEST). То есть действие команды IMUL с единственным явно заданным операндом-источником (SRC) зависит от размера этого операнда следующим образом:

  • однобайтный операнд r/m8 умножается на значение в регистре AL, результат помещается в регистр AX, флаги EFLAGS.CF и EFLAGS.OF сбрасываются, если значащие биты результата в регистре AH равны нулю (точнее — стали бы равны нулю после преобразования из дополнительного кода, см. ниже), иначе — устанавливаются в 1;
  • двухбайтный операнд r/m16 умножается на значение в регистре AX, результат помещается в пару регистров DX:AX, регистр DX содержит старшие 16 бит результата, флаги EFLAGS.CF и EFLAGS.OF сбрасываются, если значащие биты результата в регистре DX равны нулю (точнее — стали бы равны нулю после преобразования из дополнительного кода, см. ниже), иначе — устанавливаются в 1.
  • четырехбайтный операнд r/m32 умножается на значение в регистре EAX, результат помещается в пару регистров EDX:EAX, регистр EDX содержит старшие 32 бита результата, флаги EFLAGS.CF и EFLAGS.OF сбрасываются, если значащие биты результата в регистре EDX равны нулю (точнее — стали бы равны нулю после преобразования из дополнительного кода, см. ниже), иначе — устанавливаются в 1.

Форма команды с двумя операндами IMUL dest, src появилась в процессорах, начиная с Intel386. Она предполагает, что первый операнд (операнд-назначение, DEST) умножается на второй операнд (операнд-источник, SRC), а результат затем помещается в операнд-назначение (DEST). Операнд-назначение (DEST) может быть переменной в регистре (r8, r16, r32). Операнд-источник (SRC) — непосредственным значением (imm8, imm16, imm32), переменной в регистре или в памяти (r/m8, r/m16, r/m32). При этом только вариант с операндом-источником (SRC) в регистре или памяти являлся именно новой формой команды в процессорах Intel386. Форма команды с непосредственным значением в качестве второго операнда — это вырожденный вариант описываемой далее трехоперандной формы, у которой в качестве операнда-назначения (DEST) и первого операнда-источника (SRC1) задан один и тот же регистр.

Трехоперандная форма команды IMUL dest, src1, src2 была введена в процессорах, начиная с 80186/80188. В этой форме также явно задается операнд-назначение (DEST), который идет первым. Второй и третий операнды команды являются операндами-источниками (SRC1, SRC2). Операнды-источники (SRC1, SRC2) перемножаются и результат помещается в операнд-назначение (DEST). Операнд-назначение может быть только регистром общего назначения (r8, r16, r32), второй операнд (SRC1) может быть регистром и операндом в памяти (r/m8, r/m16r/m32), а третий операнд (SRC2) — это непосредственное значение (imm8, imm16, imm32).

Во всех формах команды, если в качестве множителя выступает непосредственное значение imm8 или imm16, то перед умножением оно прежде всего знакорасширяется до размера операнда-множимого, и только после этого выполняется умножение.

При использовании формы команды IMUL src с одним операндом (r/m8, r/m16, r/m32) результат умножения получается корректным, даже если будет установлен флаг переполнения (EFLAGS.OF = 1) — ведь для сохранения результата используется в два раза больше разрядов, чем для множимого и множителя. Этого достаточно, чтобы отобразить любой возможный результат. Для форм команды с двумя и тремя операндами возможна потеря старших значащих битов результата из-за переполнения, когда это происходит, флаги EFLAGS.CF и EFLAGS.OF устанавливаются.

Двух и трехоперандные формы команды IMUL могут использоваться как для манипуляции знаковыми, так и беззнаковыми целочисленными значениями. В обоих случаях результат умножения, помещаемый в операнд-назначение (DEST), идентичен и не зависит от наличия/отсутствия знакового разряда в исходных операндах. Следует только учитывать, что флаги EFLAGS.CF и EFLAGS.OF все равно устанавливаются с учетом того, что старший разряд результата предназначается для отображения знака и в случае беззнаковых операндов будут индицировать переполнение при превышении результатом всех значимых разрядов операнда-назначения согласно формата со знаком. Например, при 16-битных операндах, умножая 2 * 20000, мы получим вполне корректный 16-битный результат 40000 (в беззнаковом формате) с единицей в старшем разряде, а флаги будут указывать на переполнение, так как результат не помещается в отведенные для него (согласно формата со знаком) 15 значащих разрядов.

Для получения корректного результата и правильного срабатывания флагов переполнения (именно так, как это описано выше) во всех формах команды  IMUL при манипуляции данными в целочисленном формате со знаком целесообразно использовать дополнительный код. Строго говоря, сам процессор не знает того, в каком коде представлены данные для вычислений и получаемый результат целиком зависит от конкретных двоичных значений операндов команды. Но именно при использовании дополнительного кода показания флагов EFLAGS.CF и EFLAGS.OF будут действительно отвечать их смысловому предназначению — отражать факт переполнения (нехватки разрядности операнда-назначения для сохранения результата). Например, вполне возможно использовать и прямой код для знаковых операндов команды IMUL. Но в таком случае, вычисляя 16-битное произведение (-3 * 5 — 0x8003h * 0x0005h), мы получим в операнде-назначении (его младших 16 битах) корректный 16-битный результат в прямом коде (-15 — 0x800Fh), но флаги будут индицировать переполнение.

Для вычисления произведения целочисленных значений со знаком, кроме команды IMUL, могут также использоваться команды FIMULPMULLW и некоторые другие. Команда MUL позволяет выполнять умножение целочисленных значений в беззнаковом формате.

Операция:

IF (NumberOfOperands = 1)

   THEN

      IF (OperandSize = 8)

         THEN

            AX = AL * SRC (* Знаковое умножение *)

            IF ((AH = 0x00h) OR (AH = 0xFFh))

               THEN CF = 0; OF = 0;

               ELSE CF = 1; OF = 1;

            FI;

         ELSE

            IF (OperandSize = 16)

               THEN

                  DX:AX = AX * SRC (* Знаковое умножение *)

                  IF ((DX = 0x0000h) OR (DX = 0xFFFFh))

                     THEN CF = 0; OF = 0;

                     ELSE CF = 1; OF = 1;

                  FI;

               ELSE (* OperandSize = 32 *)

                  EDX:EAX = EAX * SRC (* Знаковое умножение *)

                  IF ((EDX = 0x00000000h) OR (EDX = 0xFFFFFFFFh))

                     THEN CF = 0; OF = 0;

                     ELSE CF = 1; OF = 1;

                  FI;

            FI;

      FI;

   ELSE

      IF (NumberOfOperands = 2)

         THEN

            temp = DEST * SRC (* Знаковое умножение; temp имеет удвоенный размер DEST *)

            DEST = DEST * SRC (* Знаковое умножение *)

            IF (temp ≠ DEST)

               THEN CF = 1; OF = 1;

               ELSE CF = 0; OF = 0;

            FI;

         ELSE (* Число операндов = 3 *)

            DEST = SRC1 * SRC2 (* Знаковое умножение *)

            temp = SRC1 * SRC2 (* Знаковое умножение; temp имеет удвоенный размер SRC1 *)

            IF (temp ≠ DEST)

               THEN CF = 1; OF = 1;

               ELSE CF = 0; OF = 0;

            FI;

      FI;

FI;

Особые ситуации защищенного режима:

#GP(0), если операнд-назначение (DEST) находится в памяти в сегменте, запрещенном для записи.
#GP(0), если при обращении к операнду в памяти в сегменте DS, ES, FS или GS используется нулевой селектор.
#GP(0), если любая часть операнда в памяти находится вне допустимого пространства эффективных адресов в сегменте CS, DS, ES, FS или GS.
#SS(0), если любая часть операнда в памяти находится вне допустимого пространства эффективных адресов в стековом сегменте SS.

Intel386 … :
#PF(Код ошибки) при страничной ошибке.
#UD при использовании префикса LOCK.

Intel486 … :
#AC(0) при невыровненной ссылке в память, если активирован контроль выравнивания (CR0.AM = 1, EFLAGS.AC = 1, CPL = 3).

Особые ситуации режима реальной адресации:

#GP, если любая часть операнда в памяти находится вне допустимого для реального режима пространства эффективных адресов в сегменте CS, DS, ES, FS или GS.
#SS, если любая часть операнда в памяти выходит за допустимую для реального режима верхнюю границу стекового сегмента SS.

Intel386 … :
#UD при использовании префикса LOCK.

Особые ситуации режима V86:

#GP(0), если любая часть операнда в памяти находится вне допустимого пространства эффективных адресов в сегменте CS, DS, ES, FS или GS.
#SS(0), если любая часть операнда в памяти находится вне допустимого пространства эффективных адресов в стековом сегменте SS.

Intel386 … :
#PF(Код ошибки) при страничной ошибке.
#UD при использовании префикса LOCK.

Intel486 … :
#AC(0) при невыровненной ссылке в память, если активирован контроль выравнивания (CR0.AM = 1, EFLAGS.AC = 1, CPL = 3).

Замечание:

К командам целочисленной арифметики относятся команды ADD, ADC, SUB, SBB, IMUL, MUL, IDIV, DIV, INC, DEC, NEGCMP.

В свою очередь, сами названные команды целочисленной арифметики делятся на следующие подгруппы:

  • команды сложения (ADDADCINC);
  • команды вычитания (SUB, SBB, DEC);
  • команды умножения (IMUL, MUL);
  • команды деления (IDIV, DIV).
  • команды сравнения и изменения знака (CMP, NEG).

Входит в группу команд: Базовая система команд CPU




Все права защищены © Алексей Ровдо, 1994-2023. Перепечатка возможна только по согласованию с владельцем авторских прав. admin@club155.ru

Top.Mail.Ru       Сервер радиолюбителей России - схемы, документация,

 соревнования, дипломы, программы, форумы и многое другое!   схемы новости электроники