2013-11-02 2 views
0

При понимании преимуществ использования языка ассемблера x86 я пытаюсь написать в качестве упражнения, 16x16 бит процедура умножения, которая принимает в два знака 16 битовых значений и умножает их с помощью сдвига и * * Addin г, и сохраняет конечную 32 битный результат в DX: AX.8086 Сборка: умножьте два 16-разрядных номера, чтобы получить результат 32 бит, не используя команду mul.

Нет проблем с запуском кода (другими словами, он компилируется просто отлично и работает с моей связанной программой), однако код не дает ожидаемого результата умножения.

Это то, что я придумал до сих пор:


В теории это должно дать мне беззнаковое 32 битный результат в DX: AX.

Когда я использую этот код в моей программе, то ниже 16 бит из 32 битного результата (или другими словами, АХ часть) правильны и показать просто отлично. более высокие 16 бит результата 32 бит (часть DX) не верны.

Может ли кто-нибудь помочь мне разобраться в том, что я делаю неправильно?

Заранее спасибо

+0

Я сомневаюсь, что это действительно быстрее, чем простой «mov ax, cx; mul bx'. Или вы пытаетесь сделать это как упражнение? – PMF

+0

@PMF В основном упражнение, чтобы понять, как это можно сделать, хотя было бы очень интересно увидеть что-то, что быстрее, чем использование команды mul (поскольку, по-видимому, она находится только за div как самая медленная инструкция на 8086). – rsxjan

+0

Да, в первой книге asm, которую я прочитал, около 20 лет назад они написали программу калькулятора, но с тех пор mul и div действительно были очень медленными, они использовали побитовые сдвиги, как вы здесь. Но я действительно был бы удивлен, если бы это было по-прежнему с сегодняшними микрокодами. – PMF

ответ

1

Кажется, что вам нужно перенести часть множимого в другой регистр после add bx, bx. Это связано с тем, что каждый раз, когда вы сдвигаете bx без сдвига переноса, верхний бит становится усеченным. Таким образом, ваш исходный код просто сохраняет сумму переносов от добавления bx к ax, а не к верхней части решения умножения, в dx.

Попробуйте это после AddToResult этикетки:

@AddToResult: 
    add bx,bx  ; add instead of shift? 
    adc di,di  ; shift part of multiplicand. 
    or cx,cx  ; fast zero check 
    jnz @lp 

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

+0

Я попытался выяснить, что не так с моим кодом, и, увидев ваше предложение и ответ, я понимаю, что это именно то, чего я отсутствовал в коде, который я опубликовал изначально. Как вы думаете, есть более эффективный способ сделать это за меньшее количество инструкций? – rsxjan

+0

Я думаю, вы могли бы удалить код перед циклом, который проверяет, являются ли оба bx и cx равными 0. Ваш результат будет по-прежнему равен 0, а умножение на 0 не является особым, чтобы иметь специальный случай. – Sean

Смежные вопросы