Ответ 1
Когда однополевая форма imul
передается 32-битным аргументом (как в вашем случае с EDX
), она фактически означает EAX * EDX
, где оба EAX
и EDX
являются 32-битными регистрами.
Произведение двух 32-битных значений не обязательно соответствует 32 битам: полный результат умножения может занимать до 64 бит. Высокие 32 бита ответа будут записаны в регистр EDX
и низкие 32 бита в регистр EAX
; это обозначается знаком EDX:EAX
.
Если вам нужны только 32 бита результата, используйте 2-операндную форму imul
; он работает быстрее и не имеет никаких неявных операндов (поэтому вы можете использовать любые регистры, которые наиболее удобны).
imul ecx, esi
делает ecx *= esi
так, как вы ожидали, не касаясь EAX
или EDX
. Это похоже на C, где unsigned x=...;
x *= y;
имеет ту же ширину для результата, что и входы.
imul
также имеет немедленную форму: imul ecx, ebx, 1234
делает ecx = ebx * 1234
. Многие ассемблеры будут принимать imul ecx, 1234
как короткие для imul ecx, ecx, 1234
.
Эти 32x32 = > 32-битные формы imul
работают правильно для подписанных или неподписанных; результаты одного операнда mul
и imul
отличаются только в верхней половине (в EDX
), а не в выводе с низким значением EAX
.