Как на самом деле imul и idiv работают 8086?

Я пытаюсь понять, как работают инструкции imul и idiv микропроцессора 8086.

Я знаю это: 1. mul и div - это умножение и деление для беззнаковых чисел 2. imul и idiv, тоже умножения и деления, но для чисел со знаком.

Я искал по всей сети, и то, что я только что написал выше, это единственная информация, которую я нашел, но написано по-разному.

У меня есть это:

mov AX, 0FFCEh
idiv AH

Поскольку это байт, AL = AX / AH (результат) и AH = остаток

После инструкции я получаю AX = 0032h, очевидно, 0 остаток, а результат 32. Может кто-нибудь объяснить, как он дошел до этого результата? Мне нужно знать, как объяснить, как работает инструкция (по крупицам).

То же самое и с инструкцией imul.

У меня есть:

mov AX, 0FF10h
imul AL

Поскольку AL является байтом, результат умножения будет сохранен в AX. Почему после выполнения инструкции imul AX = 0100h это не F100h?

Я не знаю, как на самом деле процессор выполняет mul, div, imul и idiv. Если бы кто-нибудь мог проиллюстрировать мне различия, я был бы очень признателен.

Спасибо!


person user1812076    schedule 18.02.2015    source источник
comment
Описание для IMUL r/m8 - AX <- AL * r/m byte. Итак, imul AL умножает AL на AL и сохраняет продукт в AX. В вашем случае AL содержит 10h, поэтому продукт будет 10h * 10h == 100h.   -  person Michael    schedule 18.02.2015
comment
Вы используете IDIV, он интерпретирует свои операнды как значения со знаком. Итак, это 0FFCEh / 0FFh = -50 / -1 = 50 = 32h.   -  person Hans Passant    schedule 18.02.2015
comment
Пожалуйста, поясните, о чем вы спрашиваете. Хотите узнать больше о сдвиге битов, используемом для аппаратной реализации этих инструкций? Или вы хотите узнать больше о регистрах, используемых в этих операциях, даже если они явно не указаны в инструкции? Я хотел бы помочь, но действительно не понимаю, какая часть для вас проблемна.   -  person Al Kepp    schedule 19.08.2016


Ответы (3)


idiv часть ответа

mov AX, FFCE
idiv AH

AX = FFCE

AH = FF

отрицательное определение состоит в том, что их бит наивысшего ранга равен 1, поэтому FFCE отрицателен,

потому что 1 111 1111 1100 1110

и процессор не может работать с отрицательными числами, нам нужно иметь положительное значение, это означает, что мы отрицаем это число (или процессор делает это автоматически на основе бита наивысшего ранга)

NEG FFCE

or

    1111 1111 1100 1110 => 
=>  0000 0000 0011 0001 +1 =>
=>  0000 0000 0011 0010 =>
=>  0032h

затем следующий - регистр AH равен FF - тоже отрицательный и нам нужна положительная версия, мы инвертируем

    1111 1111 =>
=>  0000 0000 +1 =>
=>  0000 0001 =>
=>  01h

затем, когда все числа положительны, мы вычисляем деление

32h div 1h, 0h остаток => AL, 32h результат => AH

оба отрицательные, что означает, что результат положительный и больше не требует преобразований.

imul часть ответа

mov AX, FF10
imul AL

AL = 10 ч.

imul / mul использует AL, когда аргумент равен 8 бит (что и есть)

поэтому imul AL такой же, как

AL * AL => 10h * 10h => 0100h = AX

imul часть ответа расширена

mov AX, FF10
imul AH

AH = FF

AL = 10 ч.

так что теперь у нас есть AL * AH => AX

AL = 10h

AH = FF, что отрицательно, нам нужно положительное, мы отрицаем и получаем => 01h

умножение положительных результатов

10h * 01h => 0010h

но так как только один из них был отрицательным, мы должны отрицать результат, не терять начальные нули, иначе ваш ответ будет неправильным

0010h => FFEF +1 => FFF0 = AX
person benkevich    schedule 17.11.2017

В статье Википедии о двоичном умножении объясняются детали битового уровня, а в есть раздел о умножении со знаком . Вы можете найти похожие детали на битовом уровне для разделения.


Но, как говорит Ганс, вам не обязательно разбираться в деталях, чтобы решить эту проблему. Вам действительно нужно знать, что в отличие от add / sub, побитовые операции mul и div отличаются для целых чисел дополнения 2 от целых чисел без знака, а не только для интерпретации результата. Интересный факт: для умножения нижняя половина результата полной ширины одинакова для mul и imul.

Таким образом, все, что вам нужно, - это описание работы с инструкциями в справочном руководстве, а также понимание того, что, например, 2 дополнение -1 представляет собой 0xFF. (См. http://www.felixcloutier.com/x86/ или исходный PDF-файл Intel: ссылки в вики-странице x86)

Интерпретируйте биты в каждом операнде так же, как и инструкция, и выполните математические вычисления «нормально». например

AX = 0xFFCE      =>   -2^16 + 0xFFCE = -0x32 = -50
AH = 0xFF        =>   -1

-50 / -1 = 50,  no remainder
person Peter Cordes    schedule 19.08.2016

Проблема, с которой вы столкнулись, частично изложена в комментариях.

mov AX, 0FFCEh
idiv AH

делит FFCE на FF. К счастью, это разделение со знаком, иначе возникнет ошибка.

Умножить намного проще:

mov AX, 0FF10h
imul AL

сохранит результат AL * AL в AX.

Остерегайтесь умножения и деления большего размера; они также используют регистр DX.

person Joshua    schedule 20.08.2016