Читаем Давайте создадим компилятор! полностью

68000 не поддерживает умножение 32 x 32, так что необходим вызов подпрограммы для программного умножения.

Он также не поддерживает умножение 8 x 8, поэтому байтовые операнды должны быть переведены до слова.

Действия, которые мы должны выполнить, лучше всего показывает следующая таблица:

T1

T2 B W L

B Преобразовать D0 в W

Преобразовать D7 в W

MULS

Result = W Преобразовать D0 в W

MULS

Result = L Преобразовать D0 в L

JSR MUL32

Result = L

W Преобразовать D7 в W

MULS

Result = L MULS

Result = L Преобразовать D0 в L

JSR MUL32

Result = L

L Преобразовать D7 в L

JSR MUL32

Result = L Преобразовать D7 в L

JSR MUL32

Result = L JSR MUL32

Result = L

Эта таблица показывает действия, предпринимаемые для каждой комбинации типов операндов. Есть три вещи, на которые необходимо обратить внимание: во-первых, мы предполагаем, что существует библиотечная подпрограмма MUL32, которая выполняет 32 x 32 умножение, оставляя 32-битное (не 64) произведение. Если в процессе этого происходит переполнение мы игнорируем его и возвращаем только младшие 32 бита.

Во-вторых, заметьте, что таблица симметрична. Наконец, обратите внимание, что произведение это всегда длинное слово, за исключением случая когда оба операнда байты. (Стоит заметить, между прочим, что это означает что результатом многих выражений будет длинное слово, нравится нам это или нет. Возможно идея перевода всех их заранее не была уж такой возмутительной, в конце концов!)

Теперь ясно, что мы должны будем генерировать различный код для 16-разрядного и 32-разрядного умножения. Для этого лучше всего иметь отдельные подпрограммы генерации кода для этих двух случаев:

{–}

{ Multiply Top of Stack by Primary (Word) }

procedure GenMult;

begin

EmitLn('MULS D7,D0')

end;

{–}

{ Multiply Top of Stack by Primary (Long) }

procedure GenLongMult;

begin

EmitLn('JSR MUL32');

end;

{–}

Исследование кода ниже для PopMul должно убедить вас, что условия в таблице выполнены:

{–}

{ Generate Code to Multiply Primary by Stack }

function PopMul(T1, T2: char): char;

var T: char;

begin

Pop(T1);

T := SameType(T1, T2);

Convert(T, 'W', 'D7');

Convert(T, 'W', 'D0');

if T = 'L' then

GenLongMult

else

GenMult;

if T = 'B' then

PopMul := 'W'

else

PopMul:= 'L';

end;

{–}

Как вы можете видеть, подпрограмма начинается совсем как PopAdd. Два аргумента приводятся к тому же самому типу. Два вызова Convert заботятся о случаях, когда оба операнда – байты. Сами данные переводятся до слова, но подпрограмма помнит тип чтобы назначать корректный тип результату. В заключение мы вызываем одну из двух подпрограмм генерации кода и затем назначаем тип результата. Не слишком сложно, действительно.

Я полагаю, что сейчас вы уже тестируете программу. Попробуйте все комбинации размеров операндов.

ДЕЛЕНИЕ

Случай с делением совсем не так симметричен. У меня также есть для вас некоторые плохие новости:

Все современные 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

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных