Методы / Мышев А.В. (ч.2)
.pdfПредполагается, что при вызове подпрограммы регистр HL адресует делимое, регистр DE – делитель, а в регистре В находится число байтов операндов. Подпрограмма начинается с проверки длины операндов и сразу осуществляет возврат, если она равна нулю. Затем формируется и запоминается в слове COUNT счетчик битов, а обе буферные области очищаются. С помощью команд SHLD производится инициализация слов PTRl и PTR2, служащих указателями буферов.
Программа 5.11. Деление беззнаковых чисел произвольной длины
;Начальный адрес делимого в HL, начальный адрес делителя
;в DE, длина операндов в регистре В. Частное возвращается на место
;делимого, а HL адресует положительный остаток.
;Если делитель равен нулю, флажок переноса установлен в единице.
DIVRND: |
|
; Проверить нулевую длину сомножителей. |
||
|
MOV |
A, B |
; Передать длину в аккумулятор |
|
|
ORA |
A |
: Возврат |
|
|
JZ |
OK |
; Возврат, если она равна нулю |
|
|
SHLD |
DVEND |
; Сохранить адрес делимого |
|
|
XCHG |
|
; Сохранить |
|
|
SHLD |
DVSOR |
; |
адрес делителя |
|
MOV |
C, B |
; Сохранить длину в регистре С |
|
|
; Отобразить счётчик битов и сохранить его в слове COUNT |
|||
|
MOV |
L,C |
;В HL длина в байтах |
|
|
MVI |
H,0 |
|
|
|
DAD |
H |
; Умножить ее на 8 |
|
|
DAD |
H |
; |
для образования счётчика битов |
|
DAD |
H |
|
|
|
INX |
H |
; |
|
SHLD: |
COUNT |
|
; Сохранить счётчик битов |
|
|
; Очистить буферые области |
|
||
|
LXI |
H,BUFF1 |
|
; Начальные адреса буферов |
|
LXI |
H,BUFF2 |
|
; в HL и DE |
|
MOV |
B, C |
; Длина в регистре В |
|
|
SUB |
A |
;Сбросить аккумулятор |
|
ZERO: |
MOV |
M, A |
; Передать ноль в текущие байты |
|
|
STAX |
D |
; |
в текущие байты буферов |
|
INX |
H |
; Продвинуть указатели |
|
|
INX |
D |
|
|
|
DCR |
B |
; Декремент счетчика байтов |
|
|
; Инициировать указатели буферов |
|||
|
LXI |
H,BUFF1 |
; Адрес первого текущего буфера |
|
|
SHLD |
PTR1 |
; |
в слове PTR1 |
51
|
LXI |
H,BUFF2 |
; Адрес второго текущего буфера |
|
|
SHLD |
PTR2 |
; |
в слове PTR2 |
|
; Проверить делитель на ноль |
|
||
|
LHLD |
DVSOR |
; В HL адрес делителя |
|
|
MOV |
B, C |
; Счетчик битов в регистре В |
|
|
SUB |
A |
; Сбросить аккумулятор |
|
CHECK: ORA |
M |
; Объеденить по ИЛИ очередной байт |
||
|
INX |
H |
; Продвинуть указатель |
|
|
DCR |
B |
; Декремент счетчика байтов |
|
|
JNZ |
CHECK |
; Повторить до завершения |
|
|
DRA |
A |
; Проверить на ноль |
|
|
JZ |
ERR |
; Ошибка, делитель равен нулю |
|
|
; Подготовка к циклу деления закончена |
|||
|
ORA |
А |
; В начале флажок переноса сброшен |
|
LOOP: |
LHLD |
DVSOR |
; Начальный адрес делителя в DE |
|
|
XCHG |
|
|
|
|
LHLD |
DVEND |
; Начальный адрес делимогов HL |
|
|
MOV |
B, C |
; Счетчик байтов в регистре В |
|
|
; Сдвинуть делимое влево с учетом флажка переноса |
|||
SHIFT1: MOV |
A, M |
; Сдвинуть очередной байт |
||
|
RAL |
|
; |
делимого |
|
MOV |
M, A |
; |
влево |
|
INX |
H |
; Продвинуть указатель |
|
|
DCR |
B |
; Декремент счетчика байтов |
|
|
JNZ |
SHIFT1 |
; Повторять до завершения |
|
|
; Проверить достижение конца цикла деления |
|||
DECR: |
LDA |
COUNT |
; Произвести декремент счетчика |
|
|
DCR |
A |
; |
битов (слова) |
|
STA |
COUNT |
; и перейти на метку ОК, |
|
|
JNZ |
COUNT |
; если деление закончено. |
|
|
LDA |
COUNT+1 |
|
; Эти команды не изменяют |
|
DCR |
A |
; состояние флажка переноса |
|
|
STA |
COUNT+1 |
|
|
|
JM |
OK |
; Деление закончено |
|
CONT: |
; Сдвинуть содержимое текущего буфера влево, |
|||
|
; передать флажок переноса в младший бит. |
|||
|
LHLD |
PTR1 |
; Сохранить флажок переноса |
|
|
MOV |
B, C |
; Проверить на ноль старший байт |
|
SHIFT2: MOV |
A, M |
; |
счетчика битов |
|
|
RAL |
|
; |
битов (слова) |
|
MOV |
M, A |
; и перейти на метку ОК, |
|
|
INX |
H |
; если деление закончено. |
|
|
DCR |
B |
; Эти команды не изменяют |
|
|
JNZ |
SHIFT2 |
; Повторять до завершения |
; Произвести вычитание, помещая разность в другой
52
|
PUSH |
B |
; Сохранить длину, освободить ВС |
|
|
MOV |
A, C |
; Образовать счетчик байтов |
|
|
STA |
LENGTH |
; в ячейке LENGTH |
|
|
LHLD |
PTR2 |
; В HL указатель другого буфера |
|
|
MOV |
C, L |
; |
передать его в ВС |
|
MOV |
B, H |
|
|
|
LHLD |
PTR1 |
; В HL указатель текущего буфера |
|
|
XCHG |
|
; |
передать его в DE |
|
LHLD |
DVSOR |
; В HL адрес делителя |
|
|
ORA |
A |
; Сбросить флажок заема |
|
SUBL: |
LDAX |
D |
; Произвести вычитание |
|
|
SBB |
M |
; |
и заполнить разность |
|
STAX |
B |
|
|
|
INX |
H |
; Продвинуть указатели |
|
|
INX |
D |
|
|
|
INX |
B |
|
|
|
LDA |
LENGTH |
; Декркмент счетчика байтов |
|
|
DCR |
A |
|
|
|
STA |
LENGTH |
|
|
|
JNZ |
SUBL |
; Повторять до завершения |
|
|
POP |
B |
; Восстановить длину операндов |
|
|
;Во флажке переноса инверсия бита частного |
|||
|
CMC |
|
; Образовать явный бит частного |
|
|
JNC |
LOOP |
; Разность отрицательна |
|
|
LHLD |
PTR1 |
; Разность положительна |
|
|
XCHG |
|
; |
необходимо скоммутировать |
|
LHLD |
PTR2 |
; |
буферы (обменять содержимое слов |
|
SHLD |
PTR1 |
; PTR1 и PTR2) |
|
|
XCHG |
|
|
|
|
SHLD |
PTR2 |
|
|
|
JMP |
LOOP |
; Повторять цикл деления |
|
ERR: |
; Ошибка - деление на ноль |
|
|
|
|
STC |
|
; Установить флажок переноса |
|
|
JMP |
EXIT |
|
|
OK: |
; состояние флажка переноса |
|
||
|
ORA |
A |
; Сбросить флажок переноса |
|
|
LHLD |
PTR1 |
; В HL начальный адрес остатка |
|
|
RET |
|
; Возвратт |
Далее осуществляется проверка делителя на ноль и, если делитель равен нулю, подпрограмма возвращается с установленным в 1 флажком переноса (метка ERR). Начиная с метки LOOP реализован «глобальный» цикл деления с образованием последовательных битов частного. Первое действие в цикле заключается в сдвиге де-
53
лимого на один бит влево (метка SHIFT1), причем выдвигаемый бит попадает во флажок переноса. После этого производится декремент счетчика битов и при достижении им нуля подпрограмма заканчивается. Если цикл деления не закончен, осуществляется сдвиг влево содержимого текущего буфера (метка SHIFT2), а затем из него вычитается делитель (метка SUBL). Как уже говорилось, формируемая разность помещается в другой буфер. В зависимости от полученной цифры частного (она определяется состоянием флажка переноса) производится (или нет) коммутация буферов, и цикл деления повторяется.
Деление знаковых целых чисел обычно выполняется следующи-
ми действиями: по знакам делимого и делителя определяется знак частного; образуются абсолютные значения операндов, т.е. операнды превращаются в беззнаковые числа, для деления которых привлекается любая из рассмотренных выше подпрограмм; с учетом знака частное представляется в дополнительном коде.
ГЛАВА 6. ОПЕРАЦИИ С ДЕСЯТИЧНЫМИ ЧИСЛАМИ
При решении некоторых задач приходится оперировать многоразрядными десятичными числами, которые, как правило, представлены в формате упакованных целых беззнаковых чисел. В МП К580 для десятичной арифметики предусмотрена единственная команда DAA десятичной коррекции аккумулятора. Она воздействует на находящуюся в аккумуляторе двоичную сумму двух байтов, содержащих упакованные десятичные числа, таким образом, что в аккумуляторе получается упакованное десятичное представление суммы, и флажок переноса показывает правильный десятичный перенос. Благодаря этой команде легко реализуются операции сложения и вычитания, но в операциях умножения и деления появляются некоторые трудности.
6.1. Сложение и вычитание
Рассмотренную выше программу 5.1 сложения двоичных целых беззнаковых чисел произвольной длины очень легко превратить в
54
программу сложения десятичных чисел: для этого достаточно после команды двоичного сложения ADC ввести команду DAA.
Установленный в 1 флажок переноса при возврате из подпрограммы сигнализирует о переполнении.
Вычитание упакованных десятичных чисел несколько усложняется тем обстоятельством, что команда DAA не корректирует результат двоичного вычитания, поэтому операцию приходится выполнять в два этапа: сначала образуется дополнение вычитаемого до 10n+l (т.е. десятичный дополнительный код), а затем полученное число суммируется с уменьшаемым. Результаты сложения можно корректировать командой DAA. В программе 6.1 приняты такие же начальные условия, как и в программе 5.1.
Программа 6.1. Сложение упакованных десятичных целых без- знаковых чисел
;Начальные адреса операндов находятся в регистрах ;HL и DE, длина (в байтах) в регистре B.
;Сумма замещает операнд, адресуемый регистром DE
; |
|
|
ADDPCK: |
XRA A |
;Сбросить флажки переноса |
LOOP: |
LDAX D |
;Текущий байт первого операнда |
|
ADC M |
;Прибавить байт второго операнда |
|
DAA |
;Скорректировать сумму |
|
STAX D |
;Сохранить текущий байт суммы |
|
IHX H |
;Продвинуть указатели |
|
IHX D |
|
|
DCR B |
;Декремент счетчика байтов |
|
JNZ LOOP |
;Повторять до завершения |
|
RET |
;Возврат |
В этой подпрограмме оригинально используется команда обмена XCHG (обменивается содержимое регистров HL и DE), благодаря которой можно обращаться к памяти короткими командами ADD М и MOV М, А. Если не использовать такого приема, в подпрограмме появляются дополнительные команды межрегистровых передач.
Образование десятичного дополнительного кода вычитаемого и сложение его с уменьшаемым реализовано в одном цикле. Десятичный дополнительный код получается путем вычитания из девяток и инкремента результата, поэтому до входа в цикл флажок переноса устанавливается в 1 командой STC. Следовательно, только
55
младший байт вычитаемого вычитается не из 99, а из 100, что эквивалентно инкременту результата. Признаком получения отрицательной разности является сброшенный в ноль флажок переноса.
6.2. Умножение
Программа 6.2. Вычитание упакованных десятичных целых беззнаковых чисел
;Адрес уменьшаемого в регистре DE, адрес вычитаемого
;в регистре HL, длина операндов (в байтах) – в регистре B. ;Разность замещает уменьшаемое.
; |
|
|
|
SUBNPK: |
STC |
|
;Для младшего байта флажок =1 |
LOOP: |
MVI |
A,99H |
;Загрузить девятки |
|
ACI |
0 |
;Учесть флажок переноса |
|
SUB |
M |
;Дополнение вычитаемого |
|
XCHG |
|
;Обменять указатели операндов |
|
ADD |
M |
;Сложить с уменьшаемым |
|
DAA |
|
;Скорректировать как сумму |
|
MOV |
M,A |
;Разность на месте уменьшаемого |
|
XCHG |
|
;Восстановить указатели |
|
IHX |
H |
;Продвинуть указатели |
|
IHX |
B |
|
|
DCR |
B |
;Декремент счетчика байтов |
|
JNZ |
LOOP |
;Повторять до завершения |
|
RET |
|
;Возврат |
При умножении упакованных десятичных чисел сохраняется общий принцип выполнения операции с двоичными числами: накапливающее суммирование множимого в зависимости от значений цифр множителя (см. рис. 5.2). Однако по сравнению с умножением двоичных чисел появляются некоторые особенности.
Во-первых, основной единицей обработки операндов становится десятичная цифра, т.е. четыре бита, например, сдвиги множимого и суммы частичных произведений необходимо осуществлять в цикле на четыре бита. Во-вторых, при умножении на каждую цифру множителя множимое прибавляется такое количество раз, равное значению цифры множителя (нулевые цифры, естественно, пропускаются). Каждое суммирование сопровождается командой десятичной коррекции DAA. Программа десятичного умножения содержит около 120 команд (в тексте не приводится).
56
6.3.Деление
Воперации деления упакованных десятичных чисел также со-
храняется общий принцип выполнения операции с двоичными числами: последовательные вычитания делителя из остатков (см. рис. 5.4). Но здесь, как и в операции умножения, появляются некоторые отличия. Основной единицей обработки операндов остается десятичная цифра, поэтому сдвиги остатка и частного производятся на четыре бита. При вычитании делителя из остатка фиксируется число вычитаний до получения отрицательной разности; это число вычитаний и является очередной цифрой частного. Явное вычитание заменяется операцией сложения остатка с десятичным дополнительным кодом делителя. Длина программы деления десятичных чисел произвольной длины, как и программы умножения, составляет около 120 команд.
Знаковые упакованные десятичные числа представляются в десятичном дополнительном коде. В этом формате сложение и вычитание выполняются аналогично соответствующим операциям над беззнаковыми упакованными десятичными числами (см. программы 6.1 и 6.2). Результат представляется в десятичном дополнительном коде. Умножение и деление обычно выполняются над абсолютными значениями операндов, а знак результата определяется отдельным действием.
Операции с неупакованными десятичными числами на практике почти не встречаются. Рассмотрим все же выполнение сложения и вычитания беззнаковых целых чисел в этом формате. Напомним, что байт содержит 16-ричные коды от 30Н до З9Н, соответствующие десятичным цифрам от 0 до 9. При сложении таких чисел с произвольной длиной операция начинается с младших байтов и циклически продолжается в сторону старших байтов с учетом межразрядных переносов. Команда ADC позволяет учесть межразрядный перенос, сформированный во флажке переноса. Однако фактический межразрядный перенос должен быть десятичным переносом из младшей тетрады суммируемых байтов. Поэтому в программе потребуются специальные команды, передающие межтетрадный перенос во флажок переноса. Если произвести двоичное сложение
57
двух байтов, а затем скорректировать сумму командой DAA, то интересующий нас перенос будет зафиксирован в четвертом бите аккумулятора. Его состояние необходимо передать во флажок переноса; эту функцию выполняют команды ANI, CPI и СМС.
Программа 6.3. Сложение неупакованных десятичных целых 6еззнаковых чисел
;Начальные адреса операндов находятся в регистрах ;HL и DE, длина в регистре B.
;Сумма замещает операнд, адресуемый регистром DE
; |
|
|
|
ADUNPK: |
XRA A |
;Сбросить флажок переноса |
|
|
PUSH PSW |
;Сохранить его в стеке |
|
LOOP: |
POP PSW |
;Возвратить состояние переноса |
|
|
LDAX D |
;Текущий байт первого операнда |
|
|
ADC M |
;Прибавить байт второго операнда |
|
|
DAA |
;Скорректировать сумму |
|
|
ANI 1FH |
;Выделить нужные биты |
|
|
CPI 16 |
;Передать межразрядный перенос |
|
|
CMC |
; |
во флажок переноса |
|
PUSH PSW |
;Сохранить перенос в стеке |
|
|
ORI 30H |
;Образовать код цифры |
|
|
LDAX D |
;Сохранить текущай байт суммы |
|
|
IHX H |
;Продвинуть указатели |
|
|
IHX D |
; |
|
|
DCR B |
;Декремент счетчика |
|
|
JNZ LOOP |
;Повторять до завершения |
|
|
POP PSW |
;Вернуть значение переноса |
|
|
RET |
;Возврат |
|
После команды десятичной коррекции DAA выделяются пять младших битов (команда ANI) и находящееся в них число сравнивается с 16 (команда CPI). Если оно больше или равно 16, флажок переноса сбрасывается в ноль (но десятичный перенос должен быть равен единице), а если число в аккумуляторе меньше 16, флажок переноса устанавливается в 1 (десятичный же перенос должен быть равным 0). Поэтому команда СМС инвертирования флажка переноса образует в нем правильное значение десятичного переноса. Командой PUSH PSW оно сохраняется в стеке, т.к. следующая команда ORI З0Н, образующая в аккумуляторе код цифры суммы, сбрасывает флажок переноса в 0. Следующие команды стандартным образом завершают цикл суммирования. При выходе из подпро-
58
ЛИТЕРАТУРА
1.Майров С.А., Новиков Г.Н. Принципы организации цифровых машин.
– Л.: Машиностроение, 1974. – 431с.
2.Майров С.А.,Новиков Г.Н. Структура электронных вычислительных машин.– Л: Машиностроение, 1979. – 385 с.
3.Мышев А.В. Структурная архитектура и принципы построения процессорных и запоминающих устройств. – Обнинск: ИАТЭ, 1999. – 76 с.
4.Каган Б.М. Электронные вычислительные машины и системы. – М.: Энергоатомиздат, 1991. – 591 с.
5.Преснухин Л.Н., Нестеров П.В. Цифровые вычислительные машины: Учебное пособие для вузов. – М.: Высшая школа, 1991. – 583 с.
6.Савельев А.Д. Прикладная теория цифровых автоматов: Учебник для вузов. – М.: Высшая школа, 1987. – 272 с.
7.Терехова В.Г., Мышев А.В. Методические указания к выполнению лабораторных работ по курсу «ЭВМ» – Обнинск: ИАТЭ, 1993. – 25 с.
СОДЕРЖАНИЕ
ПРЕДИСЛОВИЕ ………………………………………………………….. 3
ГЛАВА 4. АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ В ПРОЦЕССОРНОЙ СИСТЕМЕ НА БАЗЕ
ЧИПА КР580ИК80 ………………………………………... 4
4.1.ОБЩАЯ ХАРАКТЕРИСТИКА “ЧИПА” КР580ИК80 …………… 4
4.2.ПРОГРАММНАЯ МОДЕЛЬ ПРОЦЕССОРНОЙ СИСТЕМЫ …………………………………………………………. 7
4.3.СИСТЕМА КОМАНД ПРОЦЕССОРНОЙ СИСТЕМЫ …………. 18
4.4.АЛГОРИТМЫ И ПРОГРАММЫ АРИФМЕТИЧЕСКИХ
ОПЕРАЦИЙ ………………………………………………………… 29
ГЛАВА 5. ОПЕРАЦИИИ НАД ДВОИЧНЫМИ ЦЕЛЫМИ ЧИСЛАМИ В ПРОЦЕССОРНОЙ СИСТЕМЕ
КР580ИК80 …………………………………………………... 30
5.1.СЛОЖЕНИЕ И ВЫЧИТАНИЕ ………………………….………… 30
5.2.УМНОЖЕНИЕ ……………………………………………………... 35
5.3.УМНОЖЕНИЕ ДВОИЧНЫХ ЦЕЛЫХ БЕЗЗНАКОВЫХ
ЧИСЕЛ, ИМЕЮЩИХ ПРОИЗВОЛЬНУЮ ДЛИНУ ….………… 40 5.4. ДЕЛЕНИЕ …………………………………………………………... 46
ГЛАВА 6. ОПЕРАЦИИ С ДЕСЯТИЧНЫМИ ЧИСЛАМИ .………… 54
6.1.СЛОЖЕНИЕ И ВЫЧИТАНИЕ ………………………….………… 54
6.2.УМНОЖЕНИЕ ……………………………………………………... 56
6.3.ДЕЛЕНИЕ …………………………………………………………... 57 ЛИТЕРАТУРА ……………………………………………………………. 60
60