Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
| Помогли мы вам |
Сразу возникает вопрос: если регистры у нас 16-битные, то как с их помощью обрабатывать 32-битные числа? Ответ очевиден: мы просто будем задавать каждое число не одним регистром, а сразу двумя.
Только нам надо сначала определиться, какими регистрами и как мы будем для этого пользоваться. Давай не станем изобретать велосипед, а поищем подсказки в самом процессоре 8088.
У 8088 есть инструкция mul, которая умножает AX на 16-битный регистр и кладет результат в DX:AX. Также Сѓ него есть инструкция div, которая делит DX:AX РЅР° 16-битный регистр; результат попадает РІ регистр AX, а остаток — в DX. Еще Сѓ 8088 есть инструкция cwd. Она конвертирует знаковое 16-битное число из регистра AX РІ 32-битное число DX:AX.
Давай и мы, по примеру этих трех инструкций, тоже будем хранить 32-битные числа в DX:AX (РІ DX старшее слово, в AX — младшее). РќРѕ чтобы выполнять арифметические операции, нам РЅСѓР¶РЅРѕ еще РѕРґРЅРѕ 32-битное число. Его, РїРѕ аналогии СЃ первым, будем хранить РІ CX:BX (в CX старшее слово, РІ BX — младшее).
Ну вот, мы с тобой условились, где и как хранить 32-битные числа. Теперь давай реализуем для них операцию сложения и операцию вычитания. Для этого нам пригодятся инструкции adc Рё sbb. Вот так выглядит сложение.
Удивлен, что операция сложения у нас заняла всего две инструкции? Сейчас объясню, что тут происходит. Дело в том, что, когда ты выполняешь инструкцию add, РѕРЅР° РЅРµ только складывает РґРІР° числа, РЅРѕ Рё изменяет флаг переноса. РљРѕРіРґР° результат операции сложения РЅРµ умещается РІ сдвоенный байт, инструкция add помещает старшую цифру результата (это всегда единица) во флаг переноса.
Инструкция adc dx, cx выполняет РІРѕС‚ такую операцию: DX = DX + CX + перенос, то есть прибавляет к итоговому результату то значение, которое хранится во флаге переноса.
Теперь давай реализуем вычитание 32-битных чисел по такому же принципу.
Что тут происходит? Инструкция sub вычитает РёР· РѕРґРЅРѕРіРѕ числа РґСЂСѓРіРѕРµ, Р° еще изменяет флаг переноса. РљРѕРіРґР° операция вычитания делает «заем» РёР· соседнего разряда, флаг переноса устанавливается РІ единицу.
Р?нструкция sbb dx, cx выполняет вот такую операцию: DX = DX – CX – перенос, то есть вычитает РёР· итогового результата то значение, которое хранится РІРѕ флаге переноса.
Мы с тобой успешно реализовали операции сложения и вычитания. Теперь давай реализуем логическое инвертирование и арифметическое инвертирование.
Чтобы сделать логическое инвертирование 32-битного числа (not), нам надо просто переключить все биты числа на противоположные.
Если требуется выполнить арифметическое инвертирование (neg), то есть поменять знак числа, РЅСѓР¶РЅРѕ сделать то Р¶Рµ самое, РЅРѕ только прибавить единицу Рє результату.
Рђ теперь давай реализуем операцию умножения. Рто СѓР¶Рµ будет посложнее. Здесь РЅСѓР¶РЅРѕ вспомнить то, что ты изучал РІ начальной школе.
Ты же, надеюсь, еще не разучился умножать числа в столбик? На всякий случай напомню, что мы тут делаем.
Поочередно, справа налево, умножаем каждую цифру множимого на вторую цифру множителя. Так у нас получается первая строчка промежуточного результата. Затем умножаем каждую цифру множимого на первую цифру множителя. Так у нас получается вторая строчка промежуточного результата. Затем сдвигаем вторую строчку на один разряд влево и суммируем два промежуточных результата.
Получается, чтобы перемножить два двузначных числа, нам нужно выполнить четыре операции умножения. А если надо перемножить числа большей разрядности, то операций умножения потребуется еще больше.
РќРѕ это если «в роли цифры» Сѓ нас выступают цифры РѕС‚ 0 до 9. Однако, зная, что Сѓ процессора 8088 есть инструкция для умножения 16-битных чисел, РјС‹ для удобства можем РІ своем алгоритме умножения «назначить РЅР° роль цифры» сдвоенный байт. РўРѕ есть будем считать значения РІСЂРѕРґРµ 0x6725 Рё 0x1561 РЅРµ числами, Р° цифрами!
Почему это удобнее? Потому что для умножения двух 32-битных чисел (по две 16-битные цифры на каждое) нам понадобится всего четыре инструкции умножения. Тогда умножение двух 32-битных чисел можно будет реализовать вот так.
Умножение, конечно, выглядит сложновато по сравнению со сложением и вычитанием. Но не переживай, сейчас все объясню. Здесь весь алгоритм разделен на четыре операции умножения: по одной на каждое 16-битное слово. Точно так же, как на рисунке с умножением в столбик.
Кстати, если такой же алгоритм реализовывать на 32-битном процессоре, его можно расширить до операций над 64-битными числами, а если на 64-битном процессоре, то над 128-битными числами.
РќРѕ давай вернемся Рє нашему 16-битному алгоритму. Обрати внимание, здесь РїРѕРґ результат отводится только 48 Р±РёС‚. Рђ это значит, что если умножить, допустим, 0xFFFFFFFF на 0xFFFFFFFF, то старшие два байта потеряются. Чтобы они не терялись, нужно 64 бита, а не 48. Можешь в качестве домашнего задания доделать функцию — чтобы она возвращала 64-битный результат.
|
|
|


