Инструкции mul и imul умножает два целых числа. imul умножает числа со знаком, а mul - беззнаковые числа. Инструкция imul имеет следующую общую форму:
imul dest, source
Если инструкции передается два операнда, то она умножает первый операнд на второй и результат присваивает первому операнду:
dest = dest * source
Первый операнд - всегда регистр. Второй операнд может представлять регистр, переменную или константу. Оба операнда должны совпадать по размеру и могут быть 16-, 32- и 64-разрядными, за исключением констант, которые не могут превышать 32 бит (Если первый операнд 64-разрядный, то константы автоматически расширяются со знаком до 64 бит).
Пример умножения:
.code main proc mov eax, 3 imul eax, 5 ; EAX = EAX * 5 = 3 * 5 = 15 ret main endp end
Также инструкция imul может принимать три операнда:
imul dest, source, constant
Теперь умножаются втрой и третий операнд, а результат помещается в первый операнд:
dest = source * constant
Первый операнд - по прежнему регистр. Второй операнд - регистр или переменная. А третий операнд - константа. При этом операнды также должны соответствовать по разрядности, и могут быть 16-, 32- и 64-разрядными, за исключением констант, которые опять же не должны превышать 32 бит. Пример:
.code main proc mov edx, 3 imul eax, edx, 4 ; EAX = EDX * 4 = 3 * 4 = 12 ret main endp end
Если при умножении происходит переполнение (которое всегда является переполнением со знаком, поскольку imul умножает только целочисленные значения со знаком), то эта инструкция устанавливает флаги переноса CF и переполнения OF. Другие флаги - флаг знака SF и флаг нуля ZF не определены.
Инструкции mul и imul поддерживают также форму с одним операндом:
mul/imul operand8 ; результат в AX mul/imul operand16 ; результат в DX:AX mul/imul operand32 ; результат в EDX:EAX mul/imul operand64 ; результат в RDX:RAX
В качестве операнда можно передавать регистр или переменную. Единственный операнд умножается на соответствующий его размеру регистр AL/AX/EAX/RAX. Результат умножения двух n-битных значений может потребовать 2×n бит. Следовательно, если операнд - 8-битное число, то для результата может потребоваться 16 бит. Аналогично, 16-битный операнд дает 32-битный результат и т.д.
mul/imul operand8 | AX = AL × operand8 |
mul/imul operand16 | DX:AX = AX × operand16 |
mul/imul operand32 | EDX:EAX = EAX × operand32 |
mul/imul operand64 | RDX:RAX = RAX × operand64 |
В AX/EAX/RAX помещается младшая часть результата, а в DX/EDX/RDX - старшая.
Если результат умножения по количеству бит больше разрядности операндов, то инструкции mul
и imul
устанавливаются флаг переноса CF и флаг переполнения OF.
Пример использования
.code main proc xor rax, rax mov dx, 5 mov ax, 4 mul dx ; DX:AX = AX * DX = 4 * 5 = 20 ret main endp end