ГЛАВА 6. АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ НА ЭВМ VAX
В предыдущих главах были рассмотрены сложение и вычитание чисел со знаком и без знака, а также проверка и сравнение чисел со знаком. В этой главе более детально будут рассмотрены свойства чисел со знаком и без знака, а также вопросы, связанные с переполнением, умножением, делением и многократно увеличенной точностью. Будет описано много новых инструкций и показано, как с их помощью можно упростить программирование. Кроме того, будет продолжено изучение инструкций проверки, сравнения, перехода и их особенностей.
6.2. ЧИСЛА СО ЗНАКОМ И БЕЗ ЗНАКА
РАБОТА С ЧИСЛАМИ И ИХ ИНТЕРПРЕТАЦИЯОдно из преимуществ представления чисел в дополнительном коде заключается в том, что для чисел со знаком и без знака используются одинаковые алгоритмы сложения и вычитания. (Другие представления чисел со знаком, применяемые в различных ЭВМ, не обладают таким свойством.) Хотя этот факт кажется удивительным - объяснить его довольно просто. Для этой цели удобнее рассматривать 4-битовые числа, а не 8-, 16- или 32-битовые, поскольку существенно уменьшается число возможных комбинаций.
С помощью четырёх битов можно составить 2 4 , или 16, комбинаций. Как показано на рис. 6.1, можно составить схему, на которой 16 комбинаций располагаются по окружности. Это напоминает циферблат часов, на котором вместо 12 позиций - 16, а в позиции, соответствующей 12 час., помещено двоичное число 0000. Для указания одного из 16 двоичных чисел используется указатель. Прибавление к числу 1 рассматривается как перемещение указателя на одну позицию вперёд. Вычитание 1 рассматривается как перемещение указателя на одну позицию назад.
Если прибавлять единицу 16 раз подряд, указатель совершит полный оборот и вернётся в начальное положение. Математики это называют системой счисления по модулю 16 [1] . Но можно было бы назвать это ошибочным, так как очевидно, что X плюс 16 не равно X. Для того чтобы сделать эту систему счисления непротиворечивой, необходимо условиться, что где-то на циферблате должна быть точка возникновения ошибки.
Рис. 6.1. Арифметика чисел без знака
Например, эту точку можно расположить между числами 1111 и 0000. Каждый раз, когда к числу 1111 прибавляется или из числа 0000 вычитается 1, возникает ошибка, которая называется переполнением числа без знака. После того, как точка возникновения ошибки определена, каждой двоичной комбинации может быть поставлена в соответствие её десятичная интерпретация. Если двоичная комбинация 0000 является представлением десятичного нуля, то тогда комбинация 1111 должна быть представлением десятичного числа 15. В итоге будет получена система счисления по модулю 16 для чисел без знака.
Однако точку возникновения ошибки можно расположить на циферблате в каком-нибудь другом месте. В частности, её можно поместить между числами 0111 и 1000, как показано на рис. 6.2. Когда к числу 0111 прибавляется или из числа 1000 вычитается 1, возникает ошибка, называемая переполнением числа со знаком. Если двоичным комбинациям дать теперь десятичную интерпретацию, то окажется, что они представляют десятичные числа от -8 до +7. (Отметим, что если двоичная комбинация 0000 представляет десятичный нуль, то в соответствии с определением вычитания мы вынуждены интерпретировать комбинацию 1111 как десятичное число -1). В результате получим уже знакомое нам представление чисел в дополнительном коде.
Рис. 6.2. Арифметика чисел со знаком
Именно так интерпретируются двоичные числа в ЭВМ семейства VAX, только они включают не 4 бита, а 8, 16 или 32. Фактическое число битов определяется типом используемой инструкции, т.е. чем работает она с байтами, словами или длинными словами. Точка возникновения ошибки переполнения для чисел без знака, представленных в формате длинного слова, расположена между значениями ^X FFFFFFFF и ^X 00000000 , а между значениями ^X 7FFFFFFF и ^X 80000000 расположена точка возникновения ошибки переполнения для чисел со знаком, представленных в формате длинного слова.
Причины, по которым программист выбирает ту или иную систему представления чисел, зависит от требований конкретной задачи. Как будет показано в гл. 7, адреса иногда используются как данные для вычисления местоположения элементов массива. Поскольку считается, что адрес ^X 80000000 больше адреса ^X 7FFFFFFF , эти числа необходимо рассматривать как числа без знака. С другой стороны, если в результате вычислений могут получиться отрицательные числа, необходимо использовать представление чисел со знаком.
ОБРАБОТКА ПЕРЕПОЛНЕНИЯДля того чтобы программист мог обнаружить два указанных типа переполнения, в процессоре имеется два флага условий. Они называются бит С и бит V. Бит С устанавливается равным 1, когда в процессе выполнения арифметической операции происходит перенос из старшего разряда результата. Это аналогично переполнению числа без знака, показанному на рис. 6.1. В случае, если переноса не происходит, бит С сбрасывается в нуль. Бит V устанавливается в 1 в случае переполнения числа со знаком, как показано на рис. 6.2, и сбрасывается в нуль, если такого переполнения не происходит.
Для того чтобы биты С и V можно было использовать, необходимы средства для проверки их состояния. Ниже приведены инструкции, необходимые для этого:
Перейти, если бит С установлен (С = 1)
Перейти, если бит С сброшен (С = 0)
Перейти, если бит V установлен (V = 1)
Перейти, если бит V сброшен (V = 0)
В качестве примера использования этих битов приведём фрагмент программы, в котором производится сложение двух чисел со знаком, представленных в формате длинного слова, после чего происходит переход к метке ERROR , если возникает переполнение результата, а именно если результат либо меньше -2147483648, либо больше +2147483647:
Отметим, что эти четыре инструкции подобны другим инструкциям перехода и имеют такие же ограничения на диапазон адресов возможных переходов: 128 байтов, расположенных перед, и 127 байтов, расположенных после адреса в программном счётчике. В случае, если адрес перехода ERROR удалён от инструкций BVS более чем на 128 байтов, могут потребоваться инструкции JMP или BRW . Например,
ДРУГИЕ ФЛАГИ УСЛОВИЙУже было рассмотрено два флага условий: бит С и бит V. В ЭВМ семейства VAX имеется ещё два флага условий: бит N и бит Z. Все эти 4 флага называются кодами условий. Биты N и Z предназначены для упрощения проверки условий, возникающих в ходе выполнения любых арифметических операций. В гл. 5 уже рассматривались инструкции проверки и сравнения; покажем теперь, что в действительности происходит при выполнении условных переходов.
Бит N устанавливается в 1 всегда, когда результат операции отрицателен. Это происходит даже при выполнении такой простой инструкции, как MOVL . После её выполнения бит N будет установлен, если пересылаемое число отрицательно. Бит N сбрасывается, если число является положительным. На самом деле значение бита N обычно равно значению знакового или старшего бита результата. Однако переполнение может привести к тому, что знаковый бит результата будет содержать неверное значение. Фактически бит N отражает значение знакового бита правильного результата, даже если при переполнении результат не может целиком поместиться в ячейке результата операции.
Бит Z в определённом смысле аналогичен биту N. Бит Z устанавливается в 1 в случае, если результатом операции является число 0. Бит Z будет сброшен, если результат не равен 0. В том же смысле, что и бит N, бит Z отражает состояние правильного результата даже в случае переполнения. Значения битов N и Z, так же как и других битов кодов условий (битов С и V), могут проверяться с помощью инструкций перехода. Но в отличие от инструкций перехода по значению битов С и V, в мнемоническом обозначении которых фиксируется имя конкретного бита кодов условий (С или V), инструкции перехода по значению битов N и Z имеют мнемонику, обозначающую только тип условного перехода. Ниже приведены четыре инструкции, которые составляют список инструкций условных переходов по значению одного бита кодов условий:
Перейти, если предыдущий результат не равен 0, т.е. если бит Z сброшен
Перейти, если предыдущий результат равен нулю, т.е. если бит Z установлен в 1.
Перейти, если предыдущий результат больше или равен 0, т.е. если бит N сброшен
Перейти, если предыдущий результат меньше нуля, т.е. если бит N установлен в 1.
Заметьте, что эти же инструкции описывались в гл. 5. Для дополнения этого списка рассмотрим ещё две инструкции, которые осуществляют переход по комбинации значений битов кодов условий:
Перейти, если предыдущий результат больше 0, т.е. оба бита N и Z сброшены
Перейти, если предыдущий результат меньше или равен 0, т.е. если либо бит N, либо бит Z установлен в 1.
ИНСТРУКЦИИ ОБРАБОТКИ ДАННЫХИнструкции обработки данных устанавливают биты кодов условий в нулевое или единичное состояние в соответствии с результатом операции обработки данных. Такие инструкции, как MOVL , CLRL , а также логические операции не могут вызывать переполнения. При выполнении этих инструкций бит V сбрасывается, но значение бита С не изменяется. Почти то же самое происходит при выполнении инструкций проверки, рассмотренных в гл. 5. Инструкциями обработки данных являются инструкции, работающие непосредственно с данными, например MOVL , ADDL , SUBL и т.д. В отличие от них инструкции управления, такие как JMP , BRB , BNEQ и т.д., могут осуществлять проверку значений битов кодов условий, но не могут работать непосредственно с данными и, следовательно, устанавливать в необходимое состояние биты кодов условий.
Среди инструкций обработки данных имеется две дополнительные группы инструкций: TSTL , TSTW , TSTB и CMPL , CMPW , CMPB . Частично эти инструкции были описаны в гл. 5, но понять, как они работают, можно, только рассмотрев их совместно с состоянием кодов условий. По инструкции TSTL выполняется выборка элемента данных, проводится его проверка и устанавливаются в соответствующие состояния коды условий. На этом действие инструкции завершается. При выполнении инструкции данные не изменяются и не используются для других целей. Инструкция TSTL всегда сбрасывает биты V и С, поскольку проверка числа не может вызвать ни одного из видов переполнения. Биты N и Z будут устанавливаться в соответствующее состояние в зависимости от того, меньше или равно 0 просматриваемое число.
Инструкция CMPL по действию аналогична инструкции TSTL , но в отличие от неё оперирует двумя данными. По инструкции CMPL A , B происходит вычитание содержимого длинного слова с адресом B из содержимого длинного слова с адресом A , при этом результат вычитания проверяется и в соответствии с его значением устанавливаются биты кодов условий, после чего результат уничтожается. Таким образом, результат не сохраняется и содержимое длинных слов A и B не изменяется, что и позволяет использовать инструкцию CMPL так, как было показано в предыдущих главах, например:
Необходимо отметить, что инструкции условного перехода BGEQ , BGTR , BLSS и BLEQ не следует использовать при обработке чисел без знака. Например, если рассматривать содержимое длинных слов как число без знака, то число ^X FFFFFFFF больше числа ^X 00000000 . Однако операция сравнения, предшествующая инструкции BGTR , даст противоположный результат, поскольку число ^X FFFFFFFF будет рассматриваться как отрицательное, а именно как -1. Для решения этой проблемы предусмотрены четыре инструкции условного перехода, применяемые при обработке чисел без знака:
Перейти, если больше (для чисел без знака)
Перейти, если больше или равно (для чисел без знака)
Перейти, если меньше или равно (для чисел без знака)
Перейти, если меньше (для чисел без знака)
Эти инструкции имеют смысл только тогда, когда они используются совместно с инструкциями сравнения. Так, с помощью следующих инструкций можно перейти к метке 10$ , если содержимое длинного слова с адресом A больше, чем содержимое длинного слова с адресом B (в беззнаковом представлении):
Любопытно отметить, что инструкция BLSSU идентична инструкции BCS . На машинном языке эти инструкции имеют одинаковый код операции ^X 1F (см. п. 6 в упр. 6.1).
Сравнение или проверка на равенство осуществляется одинаково для чисел со знаком и без знака. Однако для того, чтобы избавить программиста от необходимости помнить, когда надо использовать различные переходы для чисел со знаком и без знака, в языке ассемблера предусмотрены мнемонические коды BEQLU и BNEQU , которые в действительности при ассемблировании переводятся в те же машинные коды операции, что и мнемоника инструкций BEQL и BNEQ . Это позволяет программисту быть последовательным и использовать символ U каждый раз, когда он имеет дело с числами без знака.
ИНСТРУКЦИИ ПРЕОБРАЗОВАНИЯ ДАННЫХ И ЗНАКАЧасто в одной задаче возникает необходимость в совместной обработке различной информации, представленной в различных форматах: байта, слова и длинного слова. Но при вычитании и сложении данных различного формата возникают трудности. Так, нельзя непосредственно сложить содержимое байта с содержимым слова. Для этого необходимо преобразовать формат байта в формат 16-битового слова. Затем содержимое полученного слова можно сложить с содержимым другого слова. С помощью следующих инструкций можно к содержимому байта с адресом B прибавить содержимое слова с адресом W :
Для выполнения этой операции требуется последовательность из трёх инструкций, а также временная память для хранения содержимого нового слова. В данном случае для этого используется регистр R0 , но можно было бы использовать и ячейку памяти. Инструкция CLRW обнуляет 16 битов регистра R0 . Затем содержимое байта с адресом B пересылается в восемь младших битов слова в регистре R0 . После этого новое содержимое слова в регистре R0 складывается с содержимым слова, расположенного по адресу W .
При применении этого способа необходимо помнить, что содержимое байта должно быть числом без знака. Поскольку инструкция CLRW обнуляет старшие 8 битов слова в регистре R0 , этот способ нельзя использовать, если содержимое байта должно интерпретироваться как число со знаком. Это означает, что содержимое регистра R0 рассматривается всегда как положительное число от 0 до 255. Для сложения чисел со знаком, представленных в различном формате, необходимо проверить значение знакового бита числа, содержащегося в байте. В случае отрицательного числа старшие биты слова в регистре R0 необходимо установить равными 1, а не 0, что может быть реализовано с помощью следующих инструкций:
Как видите, это довольно сложно. Поэтому ЭВМ семейства VAX включают группу инструкций преобразования формата, которые копируют числа со знаком, представленные в формате байта, слова или длинного слова, в области памяти требуемого формата. Приведённый ниже список включает инструкции преобразования формата, работающие с целочисленными операндами. Кроме того, существуют инструкции преобразования формата, работающие с операндами с плавающей точкой; они рассматриваются в гл. 12.
Преобразовать байт в слово
Преобразовать байт в длинное слово
Преобразовать слово в байт
Преобразовать слово в длинное слово
Преобразовать длинное слово в байт
Преобразовать длинное слово в слово
На самом деле эти инструкции действуют так же, как инструкции пересылки семейства MOV , за исключением того, что форматы операнда-источника и операнда-получателя различны. При выполнении этих инструкций значения бита N и бита Z устанавливаются в зависимости от значения результата так, как это было описано выше. Бит С всегда сбрасывается. Бит V устанавливается равным 1 в случае, если результат (число со знаком) слишком велик и выходит за пределы требуемого формата. Очевидно, что это может произойти только при выполнении инструкций, которые преобразуют большие форматы в меньшие, например CVTWB . Операнд-источник, представляющий собой слово, вполне может иметь значение больше 127 или меньше -128, но оно может не поместиться в формате байта (формат результата).
Поясним, как работают эти инструкции на примере предыдущей программы, в которой происходит сложение двух чисел со знаком, представленных в форматах байта и слова. Перепишем эту программу следующим образом:
Эти инструкции выполняют то же самое, что и предыдущая программа. Инструкции преобразования меньших форматов в большие, такие как CVTBW , заполняют старшие биты результата значением знакового бита исходного операнда. Например, содержимое байта ^X 03 будет расширено для представления в формате слова как ^X 0003 , но при преобразовании ^X 83 получается ^X FF83 .
Для инверсии знака числа используется другая группа инструкций. Приведённые ниже инструкции по действию аналогичны следующим операторам Фортрана или Паскаля:
Переслать байт с изменением знака
Переслать слово с изменением знака
Переслать длинное слово с изменением знака
Эти инструкции имеют два операнда и осуществляют пересылку дополнительного кода исходного числа, изменяющего знак числа на противоположный, в область памяти операнда-получателя. Например, инструкция
осуществит пересылку 32-битового дополнительного кода операнда-источника с адресом X в регистр R0 , изменив таким образом знак исходного числа на противоположный.
Данные инструкции обрабатывают биты N и Z обычным образом, устанавливая знак результата и признак равенства результата равным 0. Бит V устанавливается равным 1, если результат переполняет разрядную сетку. Напомним, что при представлении чисел в дополнительном коде положительных чисел будет на одно меньше, чем отрицательных. Так, самое большое по абсолютному значению отрицательное число, которое можно представить в формате слова, равно -32768, или ^X 8000 , а самое большое положительное число равно +32767, или ^X 7FFF . Поэтому не существует противоположного по знаку значения для отрицательного числа ^X 8000 , представленного в формате слова. При этом произойдёт установка бита V.
Использование бита С несколько необычно. Он устанавливается равным 1, если результат не равен 0. Это может показаться бессмысленным, но является полезным при изменении знака чисел с многократно увеличенной точностью (см. раздел этой главы, посвящённый многократно увеличенной точности). Фактически логика состоит в том, что получение противоположного по знаку значения числа эквивалентно вычитанию его из 0. Например, инструкция
установит бит С в то же состояние, что и пара инструкций
(На самом деле каждый из четырёх битов кодов условий N, Z, V и С будет установлен в обоих случаях в одно и то же состояние.) Если содержимое длинного слова с адресом X не равно 0, то в результате выполнения инструкции SUBL2 бит C установится равным 1, потому что вычитание ненулевого значения из 0 всегда вызывает переполнение числа без знака.
Инструкции преобразования формата и инструкции пересылки с изменением знака предназначены для работы с числами со знаком. Также бывает необходимо переслать число без знака в область памяти большего формата, например, чтобы сложить два числа без знака, т.е. содержимое байта и длинного слова. Инструкции преобразования формата, такие как CVTBL , не могут использоваться как надёжное средство для этой цели, поскольку содержимое байта будет в данном случае рассматриваться как число со знаком.
Одним из решений этой проблемы является использование пары инструкций для преобразования числа без знака в формате байта в формат длинного слова. Например,
Однако имеется группа инструкций, которые выполняют те же действия быстрее и занимают меньше памяти. Они работают так же, как инструкции преобразования формата, за исключением того, что их операнды интерпретируются как целые числа без знака. Кроме того, они обеспечивают только пересылку с преобразованием меньшего формата операнда в больший. Этот набор представлен ниже.
Переслать содержимое байта, дополненное незначащими нулями, в слово
Переслать содержимое байта, дополненное незначащими нулями, в длинное слово
Переслать содержимое слова, дополненное незначащими нулями, в длинное слово
Эти инструкции обнуляют старшие биты операнда-получателя и пересылают значение операнда-источника в младшие биты операнда-получателя. Бит V сбрасывается, так как переполнения, очевидно, быть не может. Бит N сбрасывается, поскольку в знаковый бит операнда-получателя засылается нуль. Значение бита С не изменяется.
Может показаться странным, что нет инструкций преобразования большего формата в меньший для чисел без знака, аналогичных, например, инструкции CVTLB , которая преобразует форматы чисел со знаком. Дело в том, что преобразовать больший формат в меньший для числа без знака можно с помощью обычной инструкции пересылки. Например, инструкция
осуществит пересылку младших восьми битов длинного слова с адресом L в байт с адресом B . Однако инструкция CVTLB имеет преимущество, так как позволяет обнаруживать ошибки. Признаком ошибки является установка бита V, которая происходит, если результат выходит за рамки требуемого формата. К сожалению, такая проверка для чисел без знака невозможна, поскольку бит V устанавливается только при выполнении инструкций, работающих с числами со знаком, а бит С обычно используется как признак переноса и не может использоваться как бит признака общего переполнения.
УПРАЖНЕНИЯ 6.1
^X 011A и ^X 00FD ;
^X 6A5A и ^X 7FEC ;
^X 65ED и ^X FFEB ;
^X FFFF и ^X FFFF ;
^X 7FFF и ^X 8001 ;
^X D7B7 и ^X 6DF8 .
6.3. УМНОЖЕНИЕ И ДЕЛЕНИЕ
ОСНОВНЫЕ ИНСТРУКЦИИДля умножения целых чисел в ЭВМ VAX имеются две группы инструкций: основные инструкции и инструкции расширенной арифметики. Основные инструкции предназначены для простого умножения и деления содержимого байтов, слов и длинных слов, как таковых. Инструкции расширенной арифметики, которые будут рассматриваться позже, позволяют неограниченно расширять точность представления результата и содержат такие дополнительные операции, как вычисление остатка от деления.
В группу основных инструкций умножения и деления входят следующие:
Во многом они действуют аналогично инструкциям сложения и вычитания с двумя и тремя операндами. Например, инструкция
перемножит содержимое длинных слов с адресами A и B и поместит результат в длинное слово с адресом C . Аналогично инструкция
перемножит содержимое байтов с адресами X и Y и поместит результат в байт с адресом Y . Необходимо отметить, что в результате умножения могут получиться большие числа. Поэтому для предотвращения переполнения необходимы специальные меры, особенно при умножении содержимого байтов, поскольку инструкции умножения, работающие с байтами, имеют очень ограниченный диапазон возможных значений произведения.
Инструкции деления действуют аналогично, за исключением того, что в них, как и при вычитании, важен порядок следования операндов. Эти инструкции всегда осуществляют деление второго операнда на первый. Так, инструкция
разделит содержимое длинного слова с адресом B на содержимое длинного слова с адресом A и поместит частное в длинное слово с адресом C . Аналогично инструкция
разделит содержимое байта с адресом Y на содержимое байта с адресом X и поместит частное в байт с адресом Y .
Между инструкциями умножения и деления и инструкциями сложения и вычитания имеется существенное различие. Как было показано ранее, числа со знаком и без знака обрабатываются основными инструкциями сложения и вычитания одинаково; единственная разница в их обработке состоит в том, что по-разному обнаруживается и интерпретируется переполнение. Тогда как умножение и деление чисел со знаком существенно отличается от умножения и деления чисел без знака.
Все инструкции умножения и деления, описанные в этом разделе, предназначены для работы с числами со знаком. Обработка знаков чисел подчиняется обычным правилам алгебры. Умножение и деление чисел с одинаковыми знаками дают положительный результат (произведение или частное). Умножение и деление чисел с разными знаками дают отрицательный результат.
При делении целых чисел основная трудность заключается в том, что результат деления может не быть целым числом. Описанные в этом разделе инструкции целочисленного деления ЭВМ VAX используют те же правила обработки результата, что и большинство языков высокого уровня, таких как Фортран или Паскаль. Дробная часть частного всегда усекается, и результат, таким образом, "округляется" в сторону 0. Это справедливо как для положительных, так и для отрицательных результатов. Так, результат деления 7 на 2 с усечением равен 3, Аналогично результат деления -7 на 2 с усечением равен -3.
Наконец, рассмотрим, как эти инструкции воздействуют на коды условий. Как и следовало ожидать, биты N и Z устанавливаются или сбрасываются в зависимости от того, каким является результат (произведение или частное): отрицательным или равным нулю. При этом имеется в виду реальный результат, записанный в памяти, без учёта потерянных из-за переполнения или округления битов.
Бит V устанавливается при переполнении. Так как в результате умножения могут получаться большие числа, то легко понять, где именно возникает переполнение. Бит V устанавливается, если произведение слишком велико и выражается числом, которое не помещается в заданном формате результата. Другими словами, при умножении чисел в формате байта их произведение должно находиться в диапазоне значений ^X 00 - ^X 7F . При умножении чисел в формате слова значение произведения должно находиться в диапазоне значений ^X 0000 - ^X 7FFF , а в случае длинных слов значение произведения должно быть в диапазоне значений ^X 00000000 - ^X 7FFFFFFF .
Может быть непонятно, каким образом возникает переполнение при делении, поскольку частное обычно меньше делимого, которое уже находится в заданном формате. Очевидной исключительной ситуацией является деление на 0. Понятно, что при попытке деления на 0 будет установлен бит N. Но имеется ещё одна исключительная ситуация, которая является результатом асимметрии, свойственной системе представления чисел в дополнительном коде. Вспомним, что наибольшее по абсолютному значению отрицательное число в таком представлении не имеет противоположного себе по знаку. Так, в формате байта можно представить числа от -128 до +127, в формате слова - от -32768 до 32767, в формате длинного слова - от -2147483648 до +2147483647. Поэтому при выполнении арифметических операций над числами в формате слова для числа -32768 не существует числа, противоположного ему по знаку. Это означает, что инструкции DIVW2 и DIVW3 при попытке деления числа -32768 на -1 вызовут переполнение. В аналогичной ситуации возникает переполнение при выполнении инструкций деления, работающих с байтами и длинными словами. И во всех случаях произойдёт установка бита V в 1.
В заключение рассмотрим, что происходит с битом С. Вспомним, что бит С используется главным образом для операций над числами без знака, а рассматриваемые инструкции деления и умножения используются только для арифметических операций над числами со знаком. Таким образом, эти инструкции всегда сбрасывают бит С вне зависимости от значения полученного результата.
ИНСТРУКЦИИ РАСШИРЕННОГО УМНОЖЕНИЯ И ДЕЛЕНИЯПри умножении двух n-битовых чисел результат может в общем случае занимать 2*n битов. Принимая во внимание эту возможность наряду с возможностью двухкратного уменьшения разрядности числа при делении, в ЭВМ семейства VAX предусмотрены две инструкции расширенного умножения и деления. Инструкция расширенного умножения осуществляет умножение двух 32-битовых чисел со знаком, результатом является 64-битовое число со знаком. Инструкция расширенного деления осуществляет деление 64-битового числа (делимого) на 32-битовое число (делитель), в результате получается 32-битовое частное и остаток.
Ниже показано действие инструкции расширенного умножения:
где A , B , C и D являются обычными операндами. Операнды A и B - 32-битовые множитель и множимое. Операнд D - 64-битовое произведение, имеющее формат квадраслова. Операнд C - 32-битовое число со знаком, прибавляемое к 64-битовому произведению. Эта инструкция часто используется для выполнения таких операции, как перевод из одной системы счисления в другую, где реализуется функция умножения с последующим суммированием. Именно для этой цели в инструкцию EMUL включен операнд C . Если к произведению ничего прибавлять не надо, эту инструкцию всегда можно записать в виде
Отметим, что в инструкции мы впервые сталкиваемся с практическим использованием квадраслов. В гл. 3 упоминалось, что информация может пересылаться блоками размером 8, 16, 32 и 64 бита с помощью инструкций MOVB , MOVW , MOVL и MOVQ соответственно. Инструкция MOVQ осуществляет пересылку квадраслова, т.е. 64 бита или 8 байтов. Обращение к ячейкам памяти при выполнении инструкции MOVQ не представляет сложностей, поскольку эта инструкция является просто расширением других инструкций многобайтовой пересылки MOVW и MOVL . Однако если инструкция MOVQ адресуется не к ячейкам памяти, а к регистрам, то могут возникнуть трудности, связанные с тем, что разрядность регистра 32 бита. Поэтому, если операнд имеет формат квадраслова и применяется режим регистровой адресации, это означает, что операнд расположен в двух регистрах - регистре, указанном в инструкции, и регистре со следующим старшим номером. Таким образом, инструкция
поместит 32 младших бита операнда X , имеющего формат квадраслова, в регистр R0 , а старшие 32 бита этого операнда - в регистр R1 . Аналогично инструкция
поместит 64-битовое произведение операндов A и B в регистры R3 и R4 .
Инструкция расширенного деления в некотором смысле действует обратно инструкции расширенного умножения. Делимое в формате квадраслова делится на делитель, имеющий формат длинного слова. Получаемые в результате деления частное и остаток имеют формат длинных слов. Приведём формат инструкции расширенного деления:
где операнд D - 32-битовый делитель, операнд E - 64-битовое делимое, операнды F и G - 32-битовые частное и остаток. Если остаток не равен 0, его знак соответствует знаку делимого. Поскольку в этой инструкции все операнды являются числами со знаком, определение знака частного следует обычным правилам алгебры. Если делимое и делитель имеют одинаковый знак, предполагается, что частное будет положительным. Если делимое и делитель имеют разные знаки, то предположительно частное будет отрицательным. В действительности знак частного может отличаться от предполагаемого в случае, если частное равно нулю или произошло переполнение.
Переполнение может возникать по двум причинам. Бит V установится при делении на 0. Но при делении 64-битового числа на 32-битовое число не гарантируется получение 32-битового результата. Например, деление числа ^X 000123456789ABCD на число ^X 0000100 даёт частное ^X 00000123456789AB и остаток ^X 000000CD . Отметим, что остаток всегда меньше делителя и, следовательно, должен поместиться в 32 битах. Частное в этом случае не умещается в формате длинного слова, и, следовательно, произойдёт переполнение.
Последнее замечание касается того, что инструкции расширенного умножения и деления в некотором роде симметричны. В частности, операнд-слагаемое в инструкции EMUL является отчасти дополнением остатка в инструкции EDIV . Например, рассмотрим расширенное деление
Если при выполнении этой инструкции не возникло переполнения, то расширенное умножение
даст результат в формате квадраслова (операнд X ), идентичный по значению делимому (операнд E ) в инструкции EDIV , имеющему такой же формат.
При выполнении этих инструкций биты N и Z устанавливаются в зависимости от значения результата: в случае инструкции EMUL - произведения, в случае инструкции EDIV - частного. Бит V установится, если при выполнении инструкции EDIV возникнет переполнение. При выполнении инструкции EMUL переполнение невозможно, так как 32-битовые операнды при умножении всегда дают результат, занимающий не более 64 бита. Бит С, так же как и в случае основных инструкций умножения и деления, всегда сбрасывается.
6.4. АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ С ПОВЫШЕННОЙ ТОЧНОСТЬЮ
ПРЕДСТАВЛЕНИЕ С ДВОЙНОЙ ТОЧНОСТЬЮКак было показано выше, существуют инструкции сложения и вычитания для чисел в формате байтов (8 битов), слов (16 битов) и длинных слов (32 бита). В форматах байтов и слов можно представить числа весьма ограниченного диапазона, но даже в формате длинного слова не всегда удаётся представить требуемое число. Числа без знака, представляемые в формате длинного слова, имеют значения от 0 до 4294967295. Представленные в этом же формате числа со знаком могут иметь значения от -2147483648 до +2147483647. Казалось бы, такой диапазон достаточно велик для большинства задач, однако существуют некоторые задачи, оперирующие большими числами. Для того чтобы вычислительная система была универсальной, в ней должны быть предусмотрены возможности работы с любыми числами.
Существует только один способ представления числа, не помещающегося в одной ячейке памяти, - использовать для его хранения несколько ячеек. Очевидный способ - размещение числа в двух ячейках, что называется представлением числа с двойной точностью.
Число с двойной точностью можно воспринимать просто как 64-битовое число или квадраслово. Оно может размещаться в двух длинных словах: 32 старших бита в одном длинном слове и 32 младших бита - в другом. Часто бывает удобно рассматривать эту пару длинных слов как одно 64-битовое квадраслово. При этом становится очевидной возможность представления 64-битовых чисел как со знаком, так и без знака. Для этого требуется только обобщить идею арифметики в дополнительных кодах и расширить её область применения с 32-битовых на область 64-битовых чисел. Как и раньше, крайний левый бит всего числа целиком является знаковым. Им мог бы быть знаковый бит старшего из двух длинных слов, используемых для представления числа. (Отметим, что знаковый бит младшего длинного слова является просто одним из битов в середине числа и не имеет отношения к знаку всего числа.)
СЛОЖЕНИЕ И ВЫЧИТАНИЕ ЧИСЕЛ С ДВОЙНОЙ ТОЧНОСТЬЮСпособность представления чисел с двойной точностью сама по себе малоприменима, если отсутствует возможность выполнения над этими большими числами арифметических операций. На самом деле, как будет видно из следующих примеров, основные арифметические операции можно реализовать довольно легко. Для простоты изложения представим, что шестизначные десятичные числа обрабатываются в ЭВМ, которая имеет трёхзначные десятичные слова.