Представление чисел в двоичном коде с плавающей запятой
Часто приходится обрабатывать очень большие числа (например, расстояние между звёздами) или наоборот очень маленькие числа (например, размеры атомов или электронов). При таких вычислениях пришлось бы использовать числа с очень большой разрядностью. В то же время нам не нужно знать расстояние между звёздами с точностью до миллиметра. Для вычислений с такими величинами числа с фиксированной запятой неэффективны.
В десятичной арифметике для записи таких чисел используется алгебраическая форма. При этом число записывается в виде мантиссы, умноженной на 10 в степени, отображающей порядок числа, Например:
0,2*105; 0,16*10-38
Для записи двоичных чисел тоже используется такая форма записи. Эта форма записи называется запись числа с плавающей точкой. Напомним, что мантисса не может быть больше единицы и после запятой в мантиссе не может записываться ноль.
Задание для лабораторной работы:
Самостоятельное задание:
Таблица 4.8 Варианты заданий для самостоятельной работы
№ Вар. |
Задание |
5 |
Произвести деление числа $A1 на $0С при помощи программы div8u_s |
Текст программы div8u_s деления 8-и разрядных целых беззнаковых чисел, оптимизированной с точки зрения времени исполнения.
Текст программы:
; ******************************************************
; BASIC .ASM template file for AVR
; ******************************************************
.include "C:\VMLAB\include\m128def.inc""; определение библиотеки МК ;ATmega128, при условии расположения программы VMLAB на
;локальном диске С
; Define here the variables
.def drem8u=r15 ;остаток
.def dres8u=r16 ;результат
.def dd8u =r16 ;делимое
.def dv8u =r17 ;делитель
reset: ; начальная метка
rjmp start
reti ; Addr $01
reti ; Addr $02
reti ; Addr $03 Вектора прерываний МК ATmega128.
reti ; Addr $04 Приведены вектора с адреса $01 по адрес $10.
reti ; Addr $05 Полностью вектора прерываний представлены
reti ; Addr $06 в приложении с назначением прерываний
reti ; Addr $07 (внешних и внутренних).
reti ; Addr $08
reti ; Addr $09
reti ; Addr $0A
reti ; Addr $0B
reti ; Addr $0C
reti ; Addr $0D
reti ; Addr $0E
reti ; Addr $0F
reti ; Addr $10
start: ldi dd8u, $A1 ; загрузить делимое
ldi dv8u, $0C ; загрузить делитель
div8u_s: sub drem8u,drem8u ; очистить остаток и перенос
rol dd8u ; делимое/результат сдвинуть влево
rol drem8u ; остаток сдвинуть влево
sub drem8u,dv8u ; остаток= остаток - делитель
brcc d8u_1 ; если результат < 0
add drem8u,dv8u ; восстановить остаток
clc ; сбросить перенос для формирования результата
rjmp d8u_2 ;иначе
d8u_1: sec ; установить перенос для формирования результата
d8u_2: rol dd8u ;делимое/результат сдвинуть влево
rol drem8u ; остаток сдвинуть влево
sub drem8u,dv8u ; остаток= остаток - делитель
brcc d8u_3 ; если результат < 0
add drem8u,dv8u ; восстановить остаток
clc ;сбросить перенос для формирования результата
rjmp d8u_4 ;иначе
d8u_3: sec ; установить перенос для формирования результата
d8u_4: rol dd8u ;делимое/результат сдвинуть влево
rol drem8u ; остаток сдвинуть влево
sub drem8u,dv8u ; остаток= остаток - делитель
brcc d8u_5 ; если результат < 0
add drem8u,dv8u ; восстановить остаток
clc ; сбросить перенос для формирования результата
rjmp d8u_6 ;иначе
d8u_5: sec ;установить перенос для формирования результата
d8u_6: rol dd8u ;делимое/результат сдвинуть влево
rol drem8u ; остаток сдвинуть влево
sub drem8u,dv8u ; остаток= остаток - делитель
brcc d8u_7 ; если результат < 0
add drem8u,dv8u ; восстановить остаток
clc ; сбросить перенос для формирования результата
rjmp d8u_8 ;иначе
d8u_7: sec ; установить перенос для формирования результата
d8u_8: rol dd8u ;делимое/результат сдвинуть влево
rol drem8u ; остаток сдвинуть влево
sub drem8u,dv8u ; остаток= остаток - делитель
brcc d8u_9 ; если результат < 0
add drem8u,dv8u ; восстановить остаток
clc ; сбросить перенос для формирования результата
rjmp d8u_10 ;иначе
d8u_9: sec ;установить перенос для формирования результата
d8u_10: rol dd8u ;делимое/результат сдвинуть влево
rol drem8u ; остаток сдвинуть влево
sub drem8u,dv8u ; остаток= остаток - делитель
brcc d8u_11 ; если результат < 0
add drem8u,dv8u ; восстановить остаток
clc ; сбросить перенос для формирования результата
rjmp d8u_12 ;иначе
d8u_11: sec ; установить перенос для формирования результата
d8u_12: rol dd8u ;делимое/результат сдвинуть влево
rol drem8u ; остаток сдвинуть влево
sub drem8u,dv8u ; остаток= остаток - делитель
brcc d8u_13 ; если результат < 0
add drem8u,dv8u ; восстановить остаток
clc ; сбросить перенос для формирования результата
rjmp d8u_14 ;иначе
d8u_13: sec ; установить перенос для формирования результата
d8u_14: rol dd8u ;делимое/результат сдвинуть влево
rol drem8u ; остаток сдвинуть влево
sub drem8u,dv8u ; остаток= остаток - делитель
brcc d8u_15 ; если результат < 0
add drem8u,dv8u ; восстановить остаток
clc ; сбросить перенос для формирования результата
rjmp d8u_16 ; иначе
d8u_15: sec ; установить перенос для формирования результата
d8u_16: rol dd8u ;делимое/результат сдвинуть влево
.exit ; конец программы
Блок-схема программы:
Выполнение программы пошагово:
Задание для индивидуальной работы:
Таблица 4.9 Варианты для индивидуальной работы
№ п/п |
Задание |
3 |
Дан массив А из 10 однобайтовых чисел. Переписать в массив В только числа, содержащие четное количество единиц. |
Текст программы:
.include "C:\VMLAB\include\m128def.inc"
;Задание символьных имён регистрам
.def A0 = r16
.def A1 = r17
.def A2 = r18
.def A3 = r19
.def A4 = r20
.def A5 = r21
.def A6 = r22
.def A7 = r23
.def A8 = r24
.def A9 = r25
.def B0 = r16
.def B1 = r17
.def B2 = r18
.def B3 = r19
.def B4 = r20
.def B5 = r21
.def B6 = r22
.def B7 = r23
.def B8 = r24
.def B9 = r25
.def prom1 = r26
.def temp1 = r27
.def temp2 = r28
reset:
rjmp start
reti ; Addr $01
reti ; Addr $02
reti ; Addr $03
reti ; Addr $04
reti ; Addr $05
reti ; Addr $06 Use 'rjmp myVector'
reti ; Addr $07 to define a interrupt vector
reti ; Addr $08
reti ; Addr $09
reti ; Addr $0A
reti ; Addr $0B This is just an example
reti ; Addr $0C Not all MCUs have the same
reti ; Addr $0D number of interrupt vectors
reti ; Addr $0E
reti ; Addr $0F
reti ; Addr $10
start:
;Присвоение элементам массива А числовых значений
ldi A0, 0
ldi A1, 1
ldi A2, 2
ldi A3, 3
ldi A4, 4
ldi A5, 5
ldi A6, 6
ldi A7, 7
ldi A8, 8
ldi A9, 9
mov prom1, A0 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если в последнем разряде 1, пропуститься след команда
SBRC temp1, 0
ldi prom1,0
ldi A0, 0
ldi B0, 0
cp prom1, temp2
mov B0, prom1
mov prom1, A1 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A1, 0
ldi B1, 0
cp prom1, temp2
mov B1, prom1
mov prom1, A2 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cpi temp1, 0 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A2, 0
ldi B2, 0
cp prom1, temp2
mov B2, prom1
mov prom1, A3 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A3, 0
ldi B3, 0
cp prom1, temp2
mov B3, prom1
mov prom1, A4 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A4, 0
ldi B4, 0
cp prom1, temp2
mov B4, prom1
mov prom1, A5 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A5, 0
ldi B5, 0
cp prom1, temp2
mov B5, prom1
mov prom1, A6 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A6, 0
ldi B6, 0
cp prom1, temp2
mov B6, prom1
mov prom1, A7 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A7, 0
ldi B7, 0
cp prom1, temp1
mov B7, prom1
mov prom1, A8 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A8, 0
ldi B8, 0
cp prom1, temp2
mov B8, prom1
mov prom1, A9 ;Пересылка из А0 в prom1 для сравнения
ldi temp1, 0 ;Запись в регистр
SBRC prom1, 7 ;Проверяет состояние разряда
inc temp1 ;Если в разряде 0, след команда пропустится
SBRC prom1, 6 ;Если в разряде 1,
inc temp1 ;посчитается место
SBRC prom1, 5
inc temp1
SBRC prom1, 4
inc temp1
SBRC prom1, 3
inc temp1
SBRC prom1, 2
inc temp1
SBRC prom1, 1
inc temp1
SBRC prom1, 0
inc temp1 ;В temp1 лежит число
;Проверка temp1 на чётность
cp temp1, temp2 ;Если не равно 0, то
;Проверка последнего разряда регистра
SBRS temp1, 0 ;Если последнее число 1, выполниться след команда
SBRC temp1, 0
ldi prom1,0
ldi A9, 0
ldi B9, 0
cp prom1, temp2
mov B9, prom1
.exit
Выполнение программы:
Результат выполнения программы:
Блок-схема программы:
Начало
Подключение файла m128def.inc
.include "C:\VMLAB\include\m128def.inc"
Присвоение символьных имён регистрам, загрузка символьных имён массивов, введение промежуточных переменных
.def A0 = r16 .def A1 = r17 .def A2 = r18
.def A3 = r19 .def A4 = r20 .def A5 = r21
.def A6 = r22 .def A7 = r23 .def A8 = r24
.def A9 = r25 .def B0 = r16 .def B1 = r17
.def B2 = r18 .def B3 = r19 .def B4 = r20
.def B5 = r21 .def B6 = r22 .def B7 = r23
.def B8 = r24 .def B9 = r25 .def prom1 = r26 .def temp1 = r27 .def temp2 = r28
Проверяет состояние разряда. Если в разряде 0, след команда пропустится. Если в разряде 1,посчитается место
SBRC temp0, 7
inc temp1
…..
SBRC temp0, 0
inc temp1
Проверка последнего разряда temp1, если количество единиц в элементе массива нечётно, то в prom1 ставится 0, cp temp1, temp2 SBRS temp1, 0 SBRC temp1, 0 ldi prom1,0
.
Присвоение элементам массива А числовых значений
ldi A0, 0 ldi A1, 1 ldi A2, 2 ldi A3, 3
ldi A4, 4 ldi A5, 5 ldi A6, 6 ldi A7, 7
ldi A8, 8 ldi A9, 9
Конец
Пересылка значения элемента массива в первую промежуточную переменную mov prom1, A0
Обнуление переменной перед подсчётом количества единиц в элементе массива ldi temp1, 0
Обнуление элементов массива А и В ldi A0, 0 ldi B0, 0
Если переменная со значением элемента массива не равна 0, то её значение вносится в массив В. cp prom1, 0 mov B0, prom1
Проверка разрядов для каждого из элементов массива.