Составить программу на Ассемблере с комментариями :
Подсчитать число символов в строке, расположенной в области начиная с адреса 1000H и заканчивая адресом 2000H без учета пробелов, если известно, что каждый символ занимает одну ячейку памяти и пробел кодируется как 01H.
Максимальное число символов в строке 2000h -1000h=1000h=409610
После выполнения программы результат будет помещен в HL.
LXISP,3000h; указание вершины стека
LXIH,1000h; адрес 1-го элемента => в HL
LXID,1000h; загрузка счетчика в D,E
XRAA; обнуление аккумулятора
STA2001h; обнуление счетчика количества символов
STA2002h; обнуление счетчика количества символов
MVIB,01h; код пробела => в В
LOOP:
MOVA,M; загрузить символ из ячейки М в аккумулятор
CMPB; проверка на код пробела
JNZCOUNT; если не совпадает, переход к COUNT, иначе - дальше
INXH; адрес следующего символа
DCXD; уменьшить счетчик
JZEXIT; если счетчик = 0, на выход
JMPLOOP; в начало цикла
COUNT:
PUSHH; выгрузить содержимое HL в стек
LHLD2001h; загрузить HL содержимым счетчика количества символов
INXH; увеличить счетчик на 1
SHLD2001h; сохранить счетчик количества символов в 2001h, 2002h
POPH; восстановить в HL сохраненный адрес
RET; возврат из подпрограммы
EXIT:
LHLD2001h; загрузить HL содержимым счетчика количества символов
END
Задача № 4
Составить программу на Ассемблере, направленную на решение математической функции :
Z = lg(x+1)
Натуральный и десятичный логарифмы одного и того же числа (в данном случае - выражения) связаны простым соотношением, позволяющим переходить от одного к другому :
lg x = Mlnx , где M = 1/ln10 = 0,434294481903252…
т.е., десятичный логарифм числа x = натуральному логарифму этого же числа, умноженному на постоянный множитель M = 0,434294481903252…, называемый модулем перехода от натуральных логарифмов к десятичным.
В соответствии с вышесказанным, lg (x+1) = 0,434294481903252…* ln(x+1)
Для вычисления ln(x+1) используем разложение в ряд :
ln(x+1) = x-x2/2+x3/3-x4/4+x5/5-x6/6+x7/7-x8/8+…
В результате алгоритм решения сводится к четырем арифметическим действиям : + ; - ; * ; /.
Перед выполнением арифметических действий над числами с плавающей запятой условимся первое число размещать в регистрах EHL, второе – в регистрах DBC; результат операции оставлять в EHL.
Формат представления чисел с плавающей запятой :
S
P
P
P
P
P
P
P
P
M
M
M
M
M
M
M
M
M
M
M
M
M
M
M
7
6
5
4
3
2
1
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1-й байт
2-й байт
3-й байтГде : S – знак числа ( 1-отрицательный, 0-положительный ), P0…P7 – 8-битный смещенный порядок, M1 … M15 – мантисса . Скрытый бит целой части мантиссы в нормализованных числах содержит 1
1000h
X
1001h
1003h
1003h
X2
1004h
1005h
1006h
X3
1007h
1008h
1009h
X4
100Ah
100Bh
100Ch
X5
100Dh
100Eh
100Fh
X6
1010h
1011h
1012h
X7
1013h
1014h
1020h
Адрес ячейки с текущим XN
1021h
1022h
Текущий N
До начала вычислений число Х должно быть размещено в памяти по адресам 1000h-1002h.
;начало цикла вычислений
CALC1:
LXIH,1003h; сохранение адреса первой ячейки
SHLD1020h; для хранения XN
CALLLOAD; Загрузка Х в EHL
;цикл вычисления XN
CALC2:CALLLOAD1;Загрузка Х в DBCCALLMULF; Умножение чисел с плавающей точкой
MOVB,H; HL=>BC
MOVC,L
LHLD1020h;загрузить адрес ячейки памяти для хранения Хn
MOVM,E;Хn => в память
INXH
MOVM,B
INXH
MOVM,C
INXH
SHLD1020h;запомнить адрес ячейки памяти для следующего Хn
MOVH,B;BC=>HL
MOVL,C
LDA1021h;содержимое ячейки => в аккумулятор
CPI15h;если получены все значения Хn,
JZCALC3;переход на CALC3
JMPCALC2;иначе- в начало
CALC3:
LXIH,1022h;
MVIM,01h;загрузить в ячейку 1022h делитель
LXIH,1003h;
SHLD1020h;содержимое HL => в память
;цикл вычисления XN/NCALC4:MOVB,H; HL=>BCMOVC,LLHLD1020h;загрузить адрес ячейки памяти для хранения NMOVE,M;Хn => в регистрыINXHMOVB,MINXHMOVC,MSHLD1020h;запомнить адрес ячейки памяти для следующего Хn
MOVH,B;BC=>HL
MOVL,C
PUSHH;
LXIH,1022h;N => в ячейку С
MOVC,M
POPH;
MVID,00h
MVIB,00h
CALLDIVF; Деление чисел с плавающей точкой
MOVB,H; HL=>BC
MOVC,L
LHLD1020h;загрузить адрес ячейки памяти для хранения Хn/N
DCXH;
DCXH;
MOVM,E;Хn/N => в память
INXH
MOVM,B
INXH
MOVM,C
INXH
SHLD1020h;запомнить адрес ячейки памяти для следующего Хn/N
MOVH,B;BC=>HL
MOVL,C
PUSHH;
LXIH,1022h;N => в ячейку С
MOVC,M;инкремент N
INRC
MOVM,C
POPH;
LDA1021h;содержимое ячейки => в аккумулятор
CPI15h;если получены все значения Хn,
JZCALC5;переход на CALC5
JMPCALC4;иначе- в начало
CALC5:
LXIH,1003h;
SHLD1020h;
;
CALC6:
LHLD1020h;загрузить адрес ячейки памяти для хранения N
MOVD,M;Хn/N => в регистры D,B,C.
INXH
MOVB,M
INXH
MOVC,M
INXH
SHLD1020h;запомнить адрес ячейки памяти для следующего Хn/N
;
;вычисление ln(x+1)
CALC7:CALLLOAD; Загрузка Х в EHLCALLSUBF; Вычитание чисел с плавающей точкой CALLCALC8; загрузка Хn+1/N+1 в регистры D,B,C.CALLADDF; Сложение чисел с плавающей точкой CALLCALC8; загрузка Хn+1/N+1 в регистры D,B,C.CALLSUBF; Вычитание чисел с плавающей точкой
CALLCALC8; загрузка Хn+1/N+1 в регистры D,B,C.
CALLADDF; Сложение чисел с плавающей точкой
CALLCALC8; загрузка Хn+1/N+1 в регистры D,B,C.
CALLSUBF; Вычитание чисел с плавающей точкой
CALLCALC8; загрузка Хn+1/N+1 в регистры D,B,C.
CALLADDF; Сложение чисел с плавающей точкой
CALLCALC8; загрузка Хn+1/N+1 в регистры D,B,C.
MVID,00h; загрузка модуля пере-
MVIB,2Bh; хода в DBC
MVIC,2Bh
CALLMULF; Умножение ln(x+1) на модуль перехода к lg
JMPEXIT; на выход
;;загрузка Хn+1/N+1 в регистры D,B,C.CALC8:PUSHHLHLD1020h;загрузить адрес ячейки памяти для хранения NMOVD,M;Хn/N => в регистры D,B,C.INXHMOVB,MINXHMOVC,MINXHSHLD1020h;запомнить адрес ячейки памяти для следующего Хn/N
POPH;
RET;
;
EXIT:
HLT; Останов
;
;
;
;Загрузка Х в EHLLOAD:LXIH,1000h;загрузка в HL адреса порядка ХMOVE,M;загрузка порядка Х в ЕLHLD1001h;загрузка мантиссы в HL
RET;
;Загрузка Х в DBC
LOAD1:
PUSHH;выгрузка в стек HL
LXIH,1000h;загрузка в HL адреса порядка Х
MOVD,M;загрузка порядка Х в D
INXH;
MOVB,M;
INXH;
MOVC,M;загрузка мантиссы в BC
POPH;загрузка из стека HL
RET;
;Образование дополнительного кода числа в регистре HL
comp:
movA,H;
CMA;
MOVH,A;
MOVA,L;
CMA;
MOVL,A;
INXH;
RET;
;Проверка знака и образование дополнительного кода
NEG:
MOVA,E;
ORAE;
JPNOTDK;
CALLCOMP; Образование дополнительного кода числа в регистре HL
NOTDK:RET;
;Сложение чисел с плавающей точкой
ADDF:
MOVA,D;
XRAE;
JPADDF1;
MOVA,D;
XRI80H;
MOVD,A;
JMPSUBF;
;
ADDF1:
MOVA,D;
ORAB;
ORAC;
JZADDF8;
MOVA,E;
ORAH;
ORAL;
JNZADDF2;
CALLSWAP; Обмен содержимого регистров EHL и DBC
JMPADDF8;
;
ADDF2:
MOVA,D;
STASIGN;
CALLREC;
CALLSWAP; Обмен содержимого регистров EHL и DBC
CALLREC; Восстановление числа с плавающей точкой
;
MOVA,E;
SUBD;
JNCADDF3;
CALLSWAP; Обмен содержимого регистров EHL и DBC
MOVA,E;
SUBD;
;
; В EHL большее число, в аккумуляторе разность потенциалов
ADDF3:
JZADDF6;
CPI16;
JCADDF4;
JMPADDF7;
;
;Можно сдвигать мантиссу меньшего числа
ADDF4:
MOVE,A;
CALLSWAP; Обмен содержимого регистров EHL и DBC
ADDF5:
ORAA;
CALLSHIFT; Сдвиг содержимого HL вправо на 1 бит:
INRE;
DCRD;
JNZADDF5;
;
;В регистре Е общий порядок. Можно складывать мантиссы
ADDF6:
DADB;
JNCADDF7;
INRE;
JZADDF8;
ORAA;
CALLSHIFT; Сдвиг содержимого HL вправо на 1 бит:
;
ADDF7:
CALLPACK; Преобразование числа в стандартный формат
;
ADDF8:
RET;
;
;Вычитание чисел с плавающей точкой
SUBF:
MOVA,D;
XRAE;
JPSUBF1;
MOVA,D;
XRI80H;
MOVD,A;
JMPADDF; Сложение чисел с плавающей точкой
SUBF1:
MOVA,D;
ORAB;
ORAC;
JZSUBFA;
MOVA,E;
ORAH;
ORAL;
JNZSUBF2;
CALLSWAP; Обмен содержимого регистров EHL и DBC
MOVA,E;
XRI80H;
MOVE,A;
JMPSUBFA;
SUBF2:
MOVA,E;
STASIGN;
CALLREC; Восстановление числа с плавающей точкой
CALLSWAP; Обмен содержимого регистров EHL и DBC
CALLREC; Восстановление числа с плавающей точкой
MOVA,D;
SUBE;
JNZSUBF3;
MOVA,B;
CMPH;
JNZSUBF3;
MOVA,C;
CMPL;
JNZSUBF3;
MVIE,0;
LXIH,0;
JMPSUBFA;
;
;операнды не равны, необходимо вычитать
SUBF3:
JNCSUBF4;
CALLSWAP; Обмен содержимого регистров EHL и DBC
LDASIGN;
XRI80H;
STASIGN;
;
SUBF4:
MOVA,D;
SUBE;
JZSUBF7;
CPI16;
JCSUBF5;
CALLSWAP; Обмен содержимого регистров EHL и DBC
JMPSUBF;
;
;В регистре А разность порядков, в DBC больший операнд
SUBF5:
MOVE,A;
SUBF6:
ORAA;
CALLSHIFT; Сдвиг содержимого HL вправо на 1 бит:
DCRE;
JNZSUBF6;
;
;Вычесть мантиссы, результат в EHL
SUBF7:
MOVA,C;
SUBL;
MOVL,A;
MOVA,B;
SBBH;
MOVH,A;
MOVE,D;
;
;нормализовать и проверить антипереполнение
SUBF8:
MOVA,H;
ORAH;
JMSUBF9;
DCRE;
MOVA,E;
CPI0FFH;
STC;
JZSUBFA;
DADH;
JMPSUBF8;
;
SUBF9:
CALLPACK; Преобразование числа в стандартный формат
SUBFA:
RET;
;
;Умножение чисел с плавающей точкой
MULF:
MOVA,E;
ORAH;
ORAL;
JZMULF8;
MOVA,D;
ORAB;
ORAC;
JNZMULF1;
CALLSWAP; Обмен содержимого регистров EHL и DBC
JMPMULF8;
;
;операнды ненулевые, можно умножать
MULF1:
MOVA,D;
XRAE;
STASIGN;
CALLREC; Восстановление числа с плавающей точкой
CALLSWAP; Обмен содержимого регистров EHL и DBC
CALLREC; Восстановление числа с плавающей точкой
MOVA,D;
ADDE;
JCMULF2;
SUI127;
JNCMULF3;
JMPMULF8;
;
MULF2:
ADI129;
JNCMULF3;
JMPMULF8;
;
;в аккумуляторе А смещенный порядок произведения
MULF3:
MOVC,A;
MOVE,B;
MVID,0;
MOVA,H;
LXIH,0;
XCHG;
DADH;
XCHG;
;
;начало цикла умножения
MULF4:
ORAA;
RAR;
JNCMULF5;
DADD;
;
MULF5:
JZMULF6;
XCHG;
DADH;
XHG;
JMPMULF4;
;
;проверить нарушение нормализации
MULF6:
JNCMULF7;
CALLSHIFT; Сдвиг содержимого HL вправо на 1 бит:
INRC;
STC;
JZMULF8;
;
MULF7:
MOVE,C;
CALLPACK; Преобразование числа в стандартный формат
;
MULF8:
RET;
;
;Деление чисел с плавающей точкой
DIVF:
MOVA,E;
ORAH;
ORAL;
JZDIVF7;
MOVA,D;
ORAB;
ORAC;
STC;
JZDIVF7;
;операнды не равны нулю
MOVA,D;
XRAE;
STASIGN;
CALLREC; Восстановление числа с плавающей точкой
CALLSWAP; Обмен содержимого регистров EHL и DBC
CALLREC; Восстановление числа с плавающей точкой
CALLSWAP; Обмен содержимого регистров EHL и DBC
MOVA,E;
SUBD;
JNCDIVF1;
ADI127;
CMC;
JCDIVF7; возикло антипереполнение
JMPDIVF2; перейти на деление мантисс
;
DIVF1:
ADI127; прибавить смещение
JCDIVF7; возникло антипереполнение
;
;можно начинать деление мантисс
DIVF2:
STAEXP;
XCHG;
LXIH,0;
MVIA,16; инициализировать счетчик
PUSHPSW;
JMPDIVF4; войти в цикл деления
;
DIVF3:
PUSHPSW;
DADH; сдвинуть влево
XCHG; частное и остаток
DADH;
XCHG;
;
DIVF4:
PUSHD; сохранить остаок в стеке
MOVA,E; вычесть делитель из остатка
SUBC;
MOVE,A;
MOVA,D;
SBBB;
MOVD,A;
JCDIVF5;
POPPSW; удалить остаток из стека
INRL;
PUSHD;
;
DIVF5:
POPD; извлечь предыдущий остаток
POPPSW; извлечь счетчик
DCRA; декремент счетчика
JNZDIVF3; повторить цикл деления
; деление мантисс закончено
LDAEXP;
MOVE,A;
; нормализовать частное
MOVA,H;
ORAA;
JMDIVF6;
DADH;
DCRE;
CPI0FFH; проверить антипереполнение
STC;
JZDIVF7; возникло антипереполнение
;
DIVF6:
CALLPACK; Преобразование числа в стандартный формат
DIVF7:
RET;
Построить модель распределения адресного пространства с указанием диапазонов адресов в 16-й системе счисления. В качестве дешифратора адресов используется стандартный дешифратор, к информационным входам которого подключены линии А15, А12, А9 16-разрядной шины адреса.
Y0
0
X
X
0
X
X
0
X
X
X
X
X
X
X
X
X
0000h-01FFh, 0400h-05FFh, 0800h-0DFFh
2000h-21FFh, 2400h-25FFh, 2800h-2DFFh
4000h-41FFh, 4400h-45FFh, 4800h-4DFFh
6000h-61FFh, 6400h-65FFh, 6800h-6DFFh
Y1
0
X
X
0
X
X
1
X
X
X
X
X
X
X
X
X
0200h-03FFh, 0600h-07FFh, 0A00h-0FFFh
2200h-23FFh, 2600h-27FFh, 2A00h-2FFFh
4200h-43FFh, 4600h-47FFh, 4A00h-4FFFh
6200h-63FFh, 6600h-67FFh, 6A00h-6FFFh
Y2
0
X
X
1
X
X
0
X
X
X
X
X
X
X
X
X
1000h-11FFh, 1400h-15FFh, 1800h-1DFFh
3000h-31FFh, 3400h-35FFh, 3800h-3DFFh
5000h-51FFh, 5400h-55FFh, 5800h-5DFFh
7000h-71FFh, 7400h-75FFh, 7800h-7DFFh
Y3
0
X
X
1
X
X
1
X
X
X
X
X
X
X
X
X
1200h-13FFh, 1600h-17FFh, 1A00h-1FFFh
3200h-33FFh, 3600h-37FFh, 3A00h-3FFFh
5200h-53FFh, 5600h-57FFh, 5A00h-5FFFh
7200h-73FFh, 7600h-77FFh, 7A00h-7FFFh
Y4
1
X
X
0
X
X
0
X
X
X
X
X
X
X
X
X
8000h-81FFh, 8400h-85FFh, 8800h-8DFFh
A000h-A1FFh, A400h-A5FFh, A800h-ADFFh
C000h-C1FFh, C400h-C5FFh, C800h-CDFFh
E000h-E1FFh, E400h-E5FFh, E800h-EDFFh
Y5
1
X
X
0
X
X
1
X
X
X
X
X
X
X
X
X
8200h-83FFh, 8600h-87FFh, 8A00h-8FFFh
A200h-A3FFh, A600h-A7FFh, AA00h-AFFFh
C200h-C3FFh, C600h-C7FFh, CA00h-CFFFh
E200h-E3FFh, E600h-E7FFh, EA00h-EFFFh
Y6
1
X
X
1
X
X
0
X
X
X
X
X
X
X
X
X
9000h-91FFh, 9400h-95FFh, 9800h-9DFFh
B000h-B1FFh, B400h-B5FFh, B800h-BDFFh
D000h-D1FFh, D400h-D5FFh, D800h-DDFFh
F000h-F1FFh, F400h-F5FFh, F800h-FDFFh
Y7
1
X
X
1
X
X
1
X
X
X
X
X
X
X
X
X
9200h-93FFh, 9600h-97FFh, 9A00h-9FFFh
B200h-B3FFh, B600h-B7FFh, BA00h-BFFFh
D200h-D3FFh, D600h-D7FFh, DA00h-DFFFh
F200h-F3FFh, F600h-F7FFh, FA00h-FFFFh
В итоге адресное пространство размером в 64 Кбайт разбито на диапазоны для 8 устройств. В каждом диапазоне выделено 8 участков по 512 байт и 4 участка по 1536 байт.
Задача № 2
Требуется выделить зоны адресного пространства для размещения в них адресов для устройств, указанных в таблице. В качестве адресного дешифратора используется ПЗУ. Построить схемы выделения соответствующих блоков адресов и таблицу диапазонов адресов.
Так как наименьший блок имеет размер 1К ячеек, то разрешающая способность дешифратора должна обеспечивать деление адресного пространства с точностью до зон размером 1К ячеек. Анализируя шесть старших разрядов адреса, получаем необходимую точность, поскольку они делят все адресное пространство обьемом 64К ячеек на 26 = 64 части по 1К ячеек, что и требуется.
Выбираем за основу ПЗУ с 10 адресными входами 2716 ( К573РФ2 ), имеющее структуру 2К*8 бит . Выходы 00 - 05 этого ПЗУ подключаем к инверсным входам выбора кристалла соответсвующих микросхем.