ДЕЛЕНИЕ
Случай с делением совсем не так симметричен. У меня также есть для вас некоторые плохие новости:
Все современные 16-разрядные процессоры поддерживают целочисленное деление. Спецификации изготовителей описывают эту операцию как 32 x 16 бит деление, означающее, что вы можете разделить 32-разрядное делимое на 16-разрядный делитель. Вот плохая новость:
Они вам лгут!!!
Если вы не верите в это, попробуйте разделить любое большое 32-разрядное число (это означает, что оно имеет ненулевые биты в старших 16 разрядах) на целое число 1. Вы гарантированно получите исключение переполнения.
Проблема состоит в том, что эта команда в действительности требует, чтобы получаемое частное вписывалось в 16-разрядный результат. Этого не случится, если делитель достаточно большой. Когда любое число делится на единицу, частное будет конечно тем же самым, что и делимое.
С начала времен (ну во всяком случае компьютерных) архитекторы ЦПУ предусматривали этот маленький подводный камень в схеме деления. Это обеспечивает некоторую симметрию, так как это своего рода инверсия способа каким работает умножение. Но так как единица - это совершенно допустимое (и довольно частое) число для использования в качестве делителя, делению, реализованному аппаратно, требуется некоторая помощь от программистов.
Подразумевает следующее:
· | Тип частного всегда должен быть того же самого типа, что и делимое. Он независим от делителя. |
· | Несмотря на то, что ЦПУ поддерживает деление длинного слова, аппаратно предоставленной инструкции можно доверить только делимые байт и слово. Для делимых типа длинное слово нам необходима другая библиотечная подпрограмма, которая может возвращать длинный результат. |
Это похоже на работу для другой таблицы, для суммирования требуемых действий:
T1 T2 |
B |
W |
L |
B |
Преобразовать D0 в W Преобразовать D7 в L DIVS Result = B |
Преобразовать D0 в W Преобразовать D7 в L DIVS Result = W |
Преобразовать D0 в L JSR DIV32 Result = L |
W |
Преобразовать D7 в L DIVS Result = B |
Преобразовать D7 в L DIVS Result = W |
Преобразовать D0 в L JSR DIV32 Result = L |
L |
Преобразовать D7 в L JSR DIV32 Result = B |
Преобразовать D7 в L JSR DIV32 Result = W |
JSR DIV32 Result = L |
(Вы можете задаться вопросом, почему необходимо выполнять 32-разрядное деление, когда делимое, скажем, всего лишь байт. Так как число битов в результате может быть только столько, сколько и в делимом, зачем беспокоиться? Причина в том, что если делитель - длинное слово и в нем есть какие-либо установленные старшие разряды, результат деления должен быть равен нулю. Мы не смогли бы получить его, если мы используем только младшее слово делителя)
Следующий код предоставляет корректную функцию для PopDiv:
Code: |
{ Generate Code to Divide Stack by the Primary } function PopDiv(T1, T2: char): char; begin Pop(T1); Convert(T1, 'L', 'D7'); if (T1 = 'L') or (T2 = 'L') then begin Convert(T2, 'L', 'D0'); GenLongDiv; PopDiv := 'L'; end else begin Convert(T2, 'W', 'D0'); GenDiv; PopDiv := T1; end; end; {---------------------------------------------------------------} Две подпрограммы генерации кода: {---------------------------------------------------------------} { Divide Top of Stack by Primary (Word) } procedure GenDiv; begin EmitLn('DIVS D0,D7'); Move('W', 'D7', 'D0'); end; {---------------------------------------------------------------} { Divide Top of Stack by Primary (Long) } procedure GenLongDiv; begin EmitLn('JSR DIV32'); end; |
Обратите внимание, мы предполагаем, что DIV32 оставляет результат (длинное слово) в D0.
ОК, установите новые процедуры деления. Сейчас у вас должна быть возможность генерировать код для любого вида арифметических выражений. Погоняйте ее!
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!