Ушел с форума
![]() ![]() 16355 / 7671 / 1078
Регистрация: 11.11.2010
Сообщений: 13,730
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
18.12.2013, 14:15 [ТС] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ГЛАВА 19 Большинство вычислительных систем оснащается десятичными устройствами ввода-вывода (клавиатура и дисплей). Поскольку десятичная форма представления числа естественна для людей, поэтому и в вычислительных системах предусматривали обработку десятичных чисел. Практически все ранние компьютеры характеризовались представлением чисел на основе десятичных цифр. В то же время, представление чисел в двоичном виде является более экономичным с точки зрения расхода памяти (памяти всегда не хватает!). Для представления целого числа N требуется lg(N) десятичных цифр и всего лишь log2(N) двоичных цифр (бит). Поскольку для представления одной десятичной цифры требуется четыре бита, то для десятичного представления по сравнению с двоичным потребуется тем больше памяти, чем большее количество разрядов нам требуется. Причина появления команд двоично-десятичной арифметики в современных двоичных машинах состоит в следующем: полвека назад перевод десятичных чисел в двоичный код или наоборот требовал применения достаточно сложных схем-преобразователей и занимал относительно долгое время. Решаемые задачи того времени делились на две категории: научно-технические расчеты и обработка экономической информации. Первый род задач характеризуется огромным количеством вычислений при незначительном объеме ввода-вывода — программа при запуске считывала из входного потока несколько сотен чисел, затем несколько часов интенсивной обработки (например, интегральное или дифференциальное исчисление), после чего на печать выдавалось несколько строк результата. Экономические задачи отличаются интенсивным вводом-выводом, но обходятся сравнительно небольшими и достаточно простыми вычислениями — например, для расчета зарплаты требуется прочитать большое количество входной и справочной информации — табели учета рабочего времени, базовые ставки по должностям, всяческие добавки и поправки и тому подобное, а все вычисления сводятся к операциям сложения, вычитания, умножения и деления, экспоненциальная форма представления чисел не используется; после завершения расчетов печатаются огромные «простыни» (ведомости на зарплату, всевозможные отчеты и так далее). До появления в 1964 г. IBM System/360, в которой поддерживалась как двоичная, так и двоично-десятичная арифметика, производители крупных компьютеров предлагали компьютеры, хранящие числа в двоичном представлении и применяющие для обработки чисел двоичную арифметику для научных расчетов и компьютеры, хранящие числа в двоично-десятичном представлении и применяющие для обработки чисел двоично-десятичную арифметику для коммерческих приложений.ДВОИЧНО-ДЕСЯТИЧНЫЕ ЧИСЛА
Мэйнфреймы IBM имеют команды сложения, вычитания, умножения и деления упакованных BCD-чисел переменной длины от 1 до 16 байт, то есть от 1 до 31 десятичной цифры, еще один полубайт занимает знак числа. Там же существуют несколько вспомогательных команд, упрощающих работу с BCD-числами. В результате программировать обработку таких чисел достаточно просто. А вот система команд микропроцессоров x86 содержит лишь команды десятичной коррекции вроде AAM, с помощью которых можно в цикле организовать обработку BCD-данных. На x86 обработка BCD-даных относительно медленная. Там, где мэйнфрейм IBM обходится одной командой, например, десятичного умножения, на x86 выполняется цикл из нескольких команд. FPU микропроцессора x86 поддерживает несколько более расширенный набор команд, но формат BCD-чисел всегда имеет фиксированную длину в 10 байт и содержит до 18 десятичных цифр. Если значение упакованного BCD-числа является знаковым, то знаком BCD-числа считается старший бит старшей (знаковой) тетрады. Остальные биты этой тетрады значения не имеют. Разницу между упакованными BCD-числами «-49» и «+49» можно найти только в знаковой тетраде, остальные тетрады задают абсолютную величину числа:
Пример:
Команды DAA и DAS предназначены для работы с упакованными BCD-числами. Команды AAA, AAS, AAM и AAD предназначены для работы с неупакованными BCD-числами. Команда AAD — это коррекция ПЕРЕД делением, все остальные команды — коррекции ПОСЛЕ соответствующих операций. Для работы с BCD-числами в регистре EFLAGS выделен флаг AF, который отвечает за дополнительный перенос (Auxiliary carry). Флаг AF устанавливает в 1, когда арифметическая операция вызывает перенос из 3-го бита результата в 4-й или заем из 4-го бита результата в 3-й.
Сложение и вычитание двоично-десятичных Упакованные BCD-числа обрабатываются по две цифры за операцию. Для арифметических действий с BCD-числами используют те же команды, что и для двоичных чисел. Но результат арифметических операций с BCD-числами может оказаться неправильным. Команды десятичной коррекции предназначены для коррекции результата.упакованных чисел. Команды DAA и DAS (Десятичная коррекция после сложения = Decimal Adjust for Addition) (Десятичная коррекция после вычитания = Decimal Adjust for Subtraction) Десятичная коррекция после сложения DAA и десятичная коррекция после вычитания DAS используются для работы только с упакованными BCD-числами. Команды DAA и DAS работают только с байтом данных в регистре AL. Поэтому дополнительных операндов эти команды не имеют. Синтаксис команд: DAA DAS Если просуммировать два двухзначных упакованных числа 69 и 74, то мы не получим правильного результата без дополнительной корректировки. Это происходит по той причине, что процессор пытается сложить не BCD-, а двоичные числа. Должно быть
Команда DAA правильно устанавливает регистр флагов. Если в результате сложения получилось значение в диапазоне от 100 до 198, флаг переноса CF показывает перенос из старшей десятичной позиции. При нулевом результате в 1 установлен флаг нуля ZF. В случае операций с упакованными десятичными числами флаги знака SF и переполнения OF не имеют значения, хотя флаг знака устанавливается, если старший бит регистра AL равен 1. Команда DAA использует флаг дополнительного переноса AF для определения вида коррекции, но после выполнения этой команды флаг дополнительного переноса не определен. Пример, демонстрирующий сложение упакованных BCD-чисел повышенной точности.
71067+61975=133042 Сложение упакованных BCD-чисел повышенной точности похоже на двоичную арифметику с повышенной точностью, за исключением того, что после сложения каждого байта появляется команда DAA. Из-за ограничений, присущих команде DAA, в примере нельзя было сразу сложить два упакованных двоично-десятичных числа как двойные слова, а затем применить коррекцию. С упакованными двоично-десятичными числами разрешена только байтовая арифметика.Фрагмент программы демонстрирующий использование команды DAS:
71067-61975=9092 Вычитание упакованных BCD-чисел повышенной точности происходит так же, как и сложение упакованных BCD-чисел, только за вычитанием должна следовать команда DAS. Здесь тоже допустимы только байтовые операции.Типичный пример, который преподаватели любят задавать начинающим изучать ассемблер — написать программу, преобразующую двоичное число, находящееся, например, в регистре EAX в строку символов, адрес которой находится в EDI и вывести ее на экран или в файл. Ниже показаны два варианта такой программы, использующей условные переходы: 1-й вариант:
можно реже использовать условные переходы. Та же самая задача при использовании команд DAS и DAA может быть выполнена следующим образом: 1-й вариант:
должна быть таблица перекодировки:
Символьная коррекция сложения и вычитания. Команды символьной коррекции очень похожи на команды десятичной коррекции. Они следуют за сложением или вычитанием неупакованных BCD-чисел. Там же, где программа использует команды десятичной коррекции DAA и DAS для упакованных BCD-чисел, она использует символьную коррекцию для неупакованных BCD-чисел.Команды AAA и AAS (ASCII-коррекция после сложения = “ASCII Adjust after Addition”) (ASCII-коррекция после вычитания = “ASCII Adjust after Subtraction”) После сложения двух одноразрядных неупакованных BCD-чисел программа обычно выполняет команду символьной коррекции после сложения AAA, которая преобразует результат в правильное неупакованное представление двоично-десятичного числа. Правила сложения идентичны правилам для упакованных BCD-чисел. Поскольку сложение двух одноразрядных неупакованных BCD-чисел может дать в результате число больше 9, командам AAA и AAS требуется для работы не только регистр AL. В случае команды AAA младшая цифра скорректированного результата остается в регистре AL. Если десятичное сложение привело к переносу из младшей цифры, команда AAA устанавливает равными 1 флаги переноса CF и дополнительного переноса AF. В других случаях она сбрасывает их в ноль. Содержимое других флагов не определено после команды коррекции. Команды символьной коррекции отличаются от десятичных команд тем, что они влияют на содержимое регистра AH, а также устанавливают флаг переноса, если есть перенос из младшей значащей цифры. Сложим два неупакованных BCD-числа 8 и 5:
IF ((AL AND 0FH) > 9) OR (AF = 1) THEN AL = AL + 6;ELSE AF = 0;END IF AL = AL AND 0Fh Но если написать:
самом деле используется следующий псевдокод: IF ((AL AND 0Fh) > 9) OR (AF = 1)THEN AX = (AX + 0106h);ELSE AF = 0;END IF; AL = AL AND 0Fh; Для AAS существует такая же проблема, только нужно заменить «+» на «—». А как насчет флагов? AF и CF установлены как описано выше. OF остается без изменений, а SF очищается. ZF = 1, если AX=0, PF устанавливается в зависимости от значения AL (логично, не правда ли?).Символьная коррекция вычитания AAS используется в программе после вычитания одного неупакованного двоично-десятичного числа из другого, и результат этой байтовой операции должен быть помещен в регистр AL. Результат команды символьной коррекции остается в регистре AL, и если вычитание привело к появлению займа, команда AAS уменьшает регистр AH, а также устанавливает флаги переноса и дополнительного переноса. В противном случае флаги сбрасываются. Другие флаги не определены. Операндами в команде SUB должны быть правильные одноразрядные BCD-числа. Рассмотрим возможные варианты вычитания одноразрядных BCD-чисел: Из меньшего числа вычитается большее (на пример, 5—9) — для вычитания необходимо сделать заем в старшем разряде. Факт такого займа в микропроцессоре фиксируется установкой флагов CF и AF в 1 и вычитанием 1 из содержимого AH. В результате, после команды AAS в регистре AL получается правильное значение (модуль результата), которое для нашего примера (с учетом займа из старшего разряда) составляет 6. Одновременно моделируется займ из старшего разряда, что позволяет производить вычитание длинных чисел. 5 — 9 = —4 10 — 4 = 6; Из большего числа вычитается меньшее (на пример, 8—6) — для вычитания нет необходимости делать заем в старшем разряде. Поэтому производится сброс флагов CF и AF в 0, а AH не изменяется. В результате, после команды AAS в регистре AL получается правильное значение (модуль результата), которое для нашего примера составляет 2.
Подпрограммы для ASCII сложения/вычитания Выполняем ASCII сложение с использованием команды BSWAP
с использованием BSWAP
2
|
|
Новые блоги и статьи
![]() |
||||
Результаты исследования от команды MCM (март 2025 г.)
Programma_Boinc 07.04.2025
Результаты исследования от команды MCM (март 2025 г. )
В рамках наших текущих исследований мы продолжаем изучать гены, которые имеют наибольшую вероятность развития рака легких, выявленные в рамках. . .
|
Рекурсивные типы в Python
py-thonny 07.04.2025
Рекурсивные типы - это типы данных, которые определяются через самих себя или в сочетании с другими типами, которые в свою очередь ссылаются на исходный тип. В мире программирования такие структуры. . .
|
C++26: Объединение и конкатенация последовательностей и диапазонов в std::ranges
NullReferenced 07.04.2025
Работа с последовательностями данных – одна из фундаментальных задач, с которой сталкивается каждый разработчик. C++ прошел длинный путь в эволюции средств для манипуляции коллекциями – от. . .
|
Обмен данными в микросервисной архитектуре
ArchitectMsa 06.04.2025
Когда разработчики начинают погружаться в мир микросервисов, они часто сталкиваются с парадоксальным правилом: "два сервиса не должны делить один источник данных". Эта мантра звучит повсюду в. . .
|
PostgreSQL в Kubernetes: Автоматизация обслуживания с CNPG
Mr. Docker 06.04.2025
Администраторы баз данных сталкиваются с целым рядом проблем при обслуживании PostgreSQL в Kubernetes: как обеспечить правильную репликацию данных, как настроить автоматическое переключение при. . .
|
Async/await в TypeScript
run.dev 06.04.2025
Асинхронное программирование — это подход к разработке программного обеспечения, при котором операции выполняются независимо друг от друга. В отличие от синхронного выполнения, где каждая последующая. . .
|
Многопоточность в C#: Синхронизация потоков
UnmanagedCoder 06.04.2025
Многопоточное программирование стало неотъемлемой частью разработки современных приложений на C#. С появлением многоядерных процессоров возможность выполнять несколько задач параллельно значительно. . .
|
TypeScript: Классы и конструкторы
run.dev 06.04.2025
TypeScript, как статически типизированный язык, построенный на основе JavaScript, привнес в веб-разработку новый уровень надежности и структурированности кода. Одним из важнейших элементов этой. . .
|
Многопоточное программирование: Rust против C++
golander 06.04.2025
C++ существует уже несколько десятилетий и его поддержка параллелизма постепенно наращивалась со временем. Начиная с C++11, язык получил стандартную библиотеку для работы с потоками, а в последующих. . .
|
std::vector в C++: от основ к оптимизации производительности
NullReferenced 05.04.2025
Для многих программистов знакомство с std::vector происходит на ранних этапах изучения языка, но между базовым пониманием и подлинным мастерством лежит огромная дистанция. Контейнер std::vector. . .
|