Консультация № 187263
07.04.2013, 19:23
99.51 руб.
0 23 1
Здравствуйте, уважаемые эксперты!
Для учебной цели получил задания сложить два числа с плавающей точкой из диапазона [-9..9] с точностью до 4х знаков. Программу нужно написать на ассемблере для процессора архитектуры Тесей "КР1878ВЕ1".

Нашел алгоритм для работы с плавающей точкой на сайте http://nauchebe.net/2011/03/operacii-nad-chislami-s-plavayushhej-tochkoj-mk-avr/

Так как на ассемблере ни разу не писал, то не могу понять синтаксис, структуру и как складывать числа, у которых разрядность больше 8 бит. Есть сложность с условиями. При возможности добавьте пожалуйста комментарии. Спасибо!

Приложение:
http://nauchebe.net/img/mikrokont_avrm_image134.jpg
http://nauchebe.net/img/mikrokont_avrm_image140.jpg

Обсуждение

давно
Посетитель
7438
7205
08.04.2013, 01:09
общий
08.04.2013, 02:45
Здравствуйте, Игорь!
С данным процессором сталкиваться не приходилось.
Но не переживайте, ознакомлюсь и завтра-послезавтра сделаю программу
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
08.04.2013, 14:37
общий
Сделал вроде по алгоритму, но получаются странные значения.
Я пока не учитывал требования в задании, просто пробовал реализовать алгоритм, который нашел в интернете. Проверял только числа одного знака.
Прикрепленные файлы:
13062eb903473eb5658ec8ffcb2be723.txt
давно
Посетитель
7438
7205
08.04.2013, 14:46
общий
Хорошо, вечером гляну. Сейчас некогда...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
10.04.2013, 19:02
общий
Здравствуйте! Вопрос такой, верны ли блок-схемы алгоритма? Правильно ли понимаю, что число в десятичном представлении 7,75 в двоичном с плавающей точкой будет выглядеть 0.1000010.1111?
давно
Посетитель
7438
7205
10.04.2013, 23:23
общий
10.04.2013, 23:46
Здравствуйте, отвечу пока только на второй вопрос:
Вещественное число 7.75 в двоичном представлении будет иметь вид:
0.1000000|1.1111000|00000000 (40f800h)
Точки (.) делит по полям знак-порядок-мантисса, черта (|) делит по байтам.
Знак 0, т.к. число положительное.
Наше число 7.75 = 111.11, чтобы получить нормализованное число, надо
сделать так, чтобы в целой части была одна единица
Это будет 1.1111, а, значит, порядок = 2, сохраняется 2+7fh (добавляемое смещение) = 81h
Мантисса - дробная часть (т.е. 111100000000000)
Целая единица подразумевается и отбрасывается

Насчет блок-схемы - не смотрел, увы, было некогда. Как раз сегодня собирался переделать
программки для AVR. Мне гораздо проще работать с программой, чем с блок-схемой.
А там и на блок-схемы гляну...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
11.04.2013, 00:09
общий
А вообще интересно, работа с вещественными числами достаточно нетривиальна.
Неужели более простых задач не было? Мне непонятно, как можно начинать изучать ассемблер с таких задач?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
11.04.2013, 00:33
общий
Тут забавное вот что, нам читают лекцию чисто по процессорам. Сначала про тесей, потом про х86. Про ассемблер вообще ни слово. Говорят что должны уметь работать со справочниками. То что прошу, это только первое задание, второе (постараюсь выполнить на основе 1й) будет реализация на тесее алгоритма шифрования DES какой-то там, 3 и 4 будут тоже солидные задачи на х86.
давно
Посетитель
7438
7205
11.04.2013, 00:55
общий
Лады, поможем...
Кстати, блок-схема вполне адекватная... Смотрю сейчас программы на AVR.
Сегодня, наверное, ограничусь их разбором.
Программу для Тесея сделаем уже завтра...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
11.04.2013, 01:41
общий
Программы для AVR полностью соответствуют блок-схемам, работают правильно.
Единственно, пришлось править русские буквы там, где должны быть английские :)
Видать, отсканировали, распознали и выложили, не исправив... Другого объяснения не вижу
Кстати, правильный текст для AVR не интересует? Могу дать.
Завтра перейдем на Тесей
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
11.04.2013, 10:42
общий
С AVR вряд ли вообще столкнусь, но как решение понадобитьсяИнтересует
давно
Посетитель
7438
7205
14.04.2013, 04:36
общий
это ответ
Здравствуйте, Игорь!
Вот Вам программа для процессора КР1878ВЕ1
Программа является переводом программы из приведенной Вами ссылки с языка ассемблера AVR на язык КР1878ВЕ1.
Формат вещественного числа уменьшен с 4-х байт до 3-х, за счет усечения младших бит мантиссы.
Для решения поставленной задачи этого вполне достаточно.
Будут вопросы, спрашивайте в мини-форуме...
[code h=200];дадим для удобства имена используемых регистров
#define pA %a0 ;первый байт первого числа - порядок
#define mAH %a1 ;второй байт первого числа - старший байт мантиссы
#define mAL %a2 ;третий байт первого числа - младший байт мантиссы
#define pB %b0 ;первый байт второго числа - порядок
#define mBH %b1 ;второй байт второго числа - старший байт мантиссы
#define mBL %b2 ;третий байт второго числа - младший байт мантиссы
#define acc %c0 ;рабочий регистр - аккумулятор
#define sign %c1 ;регистр для хранения знака числа (вместе с порядком)

jmp Start ;<0> Начальный пуск
jmp Err ;<1> Сторожевой таймер
jmp Err ;<2> Сбой программы (стеки,память)
jmp Err ;<3> Таймер A
jmp Err ;<4>
jmp Err ;<5>
jmp Err ;<6> Порт A
jmp Err ;<7>
jmp Err ;<8>
jmp Err ;<9>
jmp Err ;<10>
jmp Err ;<11>
jmp Err ;<12>
jmp Err ;<13>
jmp Err ;<14>
jmp Err ;<15>

Err: jmp Err ;все ошибки приведут сюда

Start: ;старт программы
cst 8 ;запрещаем прерывания (IE=0)
ldr #a,40h ;Установка сегмента A
ldr #b,48h ;Установка сегмента B
ldr #c,50h ;Установка сегмента C
;первое число = 5.75 = 0.1000000|1.0111000|00000000
movl pA,40h ;знак + 7 старших бит порядка
movl mAH,0b8h ;мл бит порядка + 7 старших бит мантиссы
movl mAL,00h ;8 младших бит мантиссы
;второе число = 2.25 = 0.1000000|0.0010000|00000000
movl pB,40h ;знак + 7 старших бит порядка
movl mBH,10h ;мл бит порядка + 7 старших бит мантиссы
movl mBL,00h ;8 младших бит мантиссы

jsr AddF ;складываем

Exit: jmp Exit ;все решено, крутимся на месте.

;функция сложения двух вещественных чисел
AddF:
;проверим на совпадение знаков чисел
;нас интересует только старший бит - бит знака
mov acc, pA ;acc = pA
xor acc, pB ;acc = pA xor pB
btth acc, 1000b ;проверим старший бит результата
jeq AddF1 ;0, когда знаки одинаковые - идем дальше
;иначе
bish pB, 1000b ;меняем знак у В
jmp SubF ;и идем на вычитание! (A+(-B)=A-(+B))

AddF1: jsr cp_B_0 ;сравним В с 0
jeq Return ;результат в А

jsr cp_A_0 ;сравнение A с 0
jne AddF2 ;оба не 0 - идем дальше
;А=0, значит результатом будет В
jsr swapAB ;обмен A и В
rts ;результат в А

AddF2: mov sign, pB ;сохранение знака вместе с порядком рВ.7

;приведем числа к удобному для использования виду:
;порядок теряем (он сохранен и будет учтен позже),
;порядок полностью в байте порядка.
;в старшем байте мантиссы добавляем подразумеваемую старшую единицу
jsr rec ;восстановление первого числа в А
jsr swapAB ;теперь А=В, а В=А
jsr rec ;восстановление второго числа в А

;смотрим, какое из чисел больше, для этого сравниваем порядки чисел
mov acc, pA ;вычитание порядков acc = pА - pB
sub acc, pB
jns AddF3 ;переход, если больше 0 (второе(в А) больше первого(в В)),
jsr swapAB ; иначе обмен и
mov acc, pA ; снова вычитание acc = pA - pB
sub acc, pB

AddF3:
;меньшее число в В, большее - в А
;в acc имеем разность порядков чисел, Z=1, если 0, т.е. порядки равны
jeq AddF6 ;переход, если порядки равны
;определим, есть ли потеря значимости,
;т.е. насколько одно число больше второго.
;если больше чем на 15, то меньшее число при сдвиге просто обнулится
;и результат будет равен большему числу
cmpl acc, 16 ;сравниваем
jc AddF4 ;есть, что складывать
jmp AddF7 ;переход при потере значимости

AddF4: mov pA, acc ;разность порядков в рА
jsr swapAB ;разность теперь в рВ, мантисса большего числа в mB

;выравним порядки чисел, для этого сдвинем меньшее число (в А) на число бит,
;равное разности порядков
AddF5: jsr shift ;сдвиг в регистрах mА
inc pA ;увеличиваем порядок меньшего числа
dec pB ;уменьшаем разность порядков
jne AddF5

;порядки выравнены
AddF6: add mAL, mBL ;сладываем мл байты мантисс
adc mAH ;учтем перенос
add mAH, mBH ;ст байты мантисс

;проверим, надо ли число нормализовать, т.к. у числа должна быть целая часть, равная 1
;исходное число с единицей в старшем разряде
;если не будет переноса в бит С, то число осталось нормализованным
jnc AddF7 ;проверка нарушения нормализации
;есть нарушение, правим
inc pA ;корректируем порядок
;есть опасность переполнения, когда порядок изменится с ffh на 00h,
;проверим
stc ;взведем на всякий случай флаг ошибки
jeq Return ;выход с флагом переполнения С

jsr shift ;корректируем мантиссу сдвигом вправо

AddF7: jsr pack ;форматирование результата
Return: rts ;выход

;------------------------------------------------------
;вычитание А-В
SubF: mov acc, pA ;сравнение знаков чисел
xor acc, pB
btth acc, 1000b ;проверим старший бит результата
jeq SubF1 ;0, когда знаки одинаковые - идем дальше
;иначе
bish pB, 1000b ;изменение знака
jmp AddF ;считаем сумму A-(-B)=A+B

SubF1: jsr cp_B_0 ;проверка В на 0
jeq Return ;результат равен А

jsr cp_A_0 ;проверка A на 0
jne SubF2 ;оба не 0, идем дальше

jsr swapAB ;обмен операндов
bish pA, 1000b ; со сменой знака результата
rts ;результат A=-B

SubF2: mov sign, pA ;сохраняем знак

jsr rec ;восстановление числа А
jsr swapAB ;теперь в рА порядок 2-го числа
jsr rec ;восстановление числа В в регистрах А

;определим, какое число больше
mov acc, pB ;из порядка 1-го вычитаем
sub acc, pA ; порядок 2-го
jne SubF3 ;числа разные

cmp mBH, mAH ;при равенстве порядков
jne SubF3 ; сравниваем мантиссы

cmp mBL, mAL
jne SubF3

clr pA ;если числа равны,
clr mAH ; результат равен 0
clr mAL
rts

SubF3: jnc SubF4 ;переход, если 1-е число
; (оно в pB,mB) больше,
jsr swapAB ; иначе обмен числами
btgh sign, 1000b ; и изменение знака в sign

SubF4: mov acc, pB ;снова вычитание порядков
sub acc, pA
jeq SubF7 ;переход при одинаковых порядках

cmpl acc, 16 ;проверим на потерю значимости
jc SubF6 ;идем дальше

jsr swapAB ;передача большего числа
; в (pA,mA) перед
jmp SubF9 ; форматированием результата

SubF6: jsr shift ;сдвиг мантиссы меньшего числа
dec acc ; в mА, пока
jne SubF6 ; разность порядков не равна 0

;Вычитание мантисс и сохранение разности в mА

SubF7: sub mBL, mAL ;мл б мантиссы
mov mAL, mBL
sbc mBH ;учитываем заем
sub mBH, mAH ;ст б мантиссы
mov mAH, mBH
mov pA, pB ;передача порядка результата в pA

SubF8: btth mAH, 1000b ;проверка нарушения нормализации
jnz SubF9 ;переход, если нарушения нет,
dec pA ; иначе, не сдвигая мантиссу,
jc SubQuit ;при антипереполнении выходим
; с флагом C=1, иначе
shl mAL ; сдвигаем мантиссу mА влево
rlc mAH
cst 1 ; и сбрасываем флаг C
jmp SubF8 ;повторяем проверку

SubF9: jsr pack ;форматируем результат

SubQuit:rts ;выход из процедуры вычитания

;-------------------------------------------
;вспомогательные подпрограммы
;-------------------------------------------
;Восстановление операнда из базового формата
rec: shl mAH ;младший разряд порядка (ст бит байта) в С
rlc pA ;восстановление порядка
shr mAH ;сдвиг вправо мантиссы
bish mAH, 1000b ;восстановление скрытой 1
rts

;Упаковка в базовый формат
pack: clr pB ;здесь сформируем байт с младшим битом
; порядка на старшем месте
shl sign ;ст бит (знак) уходит в С
rrc pA ;вводим знак в рА.7, мл бит в С
rrc pB ;вводим мл бит порядка на место ст бита pB
bich mAH, 1000b ;сначала обнулим старший бит ст байта мантиссы
or mAH, pB ;пишем его на свое место
rts

;Обмен операндов
swapAB: xor pA, pB ;обмен регистров
xor pB, pA ; рА и рВ
xor pA, pB ; за три операции

xor mAL, mBL
xor mBL, mAL
xor mAL, mBL

xor mAH, mBH
xor mBH, mAH
xor mAH, mBH
rts

;сравнение А(В) с 0
cp_A_0: mov acc, pA
or acc, mAH
or acc, mAL ;при A=0 возвращает флаг Z=1
rts ;при A!=0 – Z=0

cp_B_0: mov acc, pB
or acc, mBH
or acc, mBL ;при B=0 возвращает флаг Z=1
rts ;при B!=0 – Z=0

;Сдвиг вправо 24-разрядной мантиссы mA
shift: shr mAH
rrc mAL
clc
rts

.END [/code]

Вот здесь подправленный код из приведенной Вами ссылки для AVR: avr.rar (3.1 кб)
5
Спасибо за помощь!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
15.04.2013, 11:09
общий
Ну так, компилируется или нет?...
У меня все компилируется...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
15.04.2013, 11:19
общий
Спасибо! Пока пытаюсь разобраться что к чему. Есть такой вопрос

;первое число = 5.75 = 0.1000000|1.0111000|00000000
movl pA,40h ;знак + 7 старших бит порядка
movl mAH,0b8h ;мл бит порядка + 7 старших бит мантиссы
movl mAL,00h ;8 младших бит мантиссы

Как из --> (movl mAH,0b8h) получается 1.0111000 ?
В моем понимании получается 0.0001000
давно
Посетитель
7438
7205
15.04.2013, 11:34
общий
15.04.2013, 11:35
Нолик спереди добавляется, если имеем первую hex-цифру большую 9.
Это делается, чтобы не путать с идентификаторами и метками.
Т.о., у нас 0b8h = b8h = 10111000b
(Буковка 'b' - это не binary, а шестнацитиричное b16 = 1110)
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
15.04.2013, 12:07
общий
15.04.2013, 12:35
А как мне определить что полученное число положительное или отрицательное если в ответе я получаю только порядок и мантиссу?
Что значит
#DEFINE SIGN %C1 ;регистр для хранения знака числа (вместе с порядком)?
Запустил программу, получил SIGN = 80, что это значит?

В Вашем сообщении сразу и вопрос, и ответ
Как раз данный регистр и служит для хранения знака результата, который будет учтен при формировании или упаковке окончательного результата.
Формат числа предусматривает знак в старшем бите первого байта числа. Мы его сначала сохраняем, потом вставляем.
В программе для AVR знак результата хранится в специальном бите Т. В данном же процессоре такой возможности нет, поэтому я сохраняю весь байт в %c1.
Чтобы понять, что значит SIGN=80, (а это значение будет в регистре после выполнения программы) обратите внимание на подпрограмму pack, которая формирует окончательный результат.
В ней регистр SIGN сдвигается влево на один бит. Это необходимо, чтобы старший бит (знак!) оказался в бите С.
То, что стало 80h, раньше было 40h
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
15.04.2013, 12:37
общий
15.04.2013, 12:38
Зачем было удалять сообщение?
Пришлось вставить его, как цитату, иначе непонятно, на что я отвечаю...
То, что что-то не знаете, это нормально. Главное, что есть желание разобраться
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
15.04.2013, 12:41
общий
Такой вопрос для моего понимания, как представлять числа в нужный мне формат 1,25 и 0,25?
давно
Посетитель
7438
7205
15.04.2013, 13:08
общий
15.04.2013, 13:40
1.25
Сначала преобразовываем целую часть, тут все просто: 110 = 12
С дробной не так очевидно. Очередная единица получается, как добавки 1/2, 1/4, 1/8...
Т.е., имеем 0.25:
Код:
0.5 0.25 0.125
0 1 0

0.2510 = 0.012
Вместе получаем 1.2510 = 1.012
Далее смотрим:
1) Знак = 0 (т.к. 1.25 > 0)
2) Порядок = 0, т.к. имеем нормализованное число (имеем в целой части одну 1)
Не забываем, что до порядка добавляется смещение 127 = 7fh
Т.о., порядок = 01111111b
3) Мантисса = 010...0. Помним, что единицу из целой части мы отбрасываем
Получаем:
0.0111111|1.0100000|000000002 = 3fh,0a0h,00h
0.25
0.2510 = 0.012
Число требует нормализации, получаем 0.012 = 1.0[$149$]2-2
1) знак = 0
2) порядок = -2 + 7fh = 7dh = 01111101b
3) мантисса = 0
Получаем:
0.0111110|1.0000000|000000002 = 3eh,80h,00h
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
15.04.2013, 13:31
общий
Если 2,25 - 1,75 = 0,375 это нормально?
давно
Посетитель
7438
7205
15.04.2013, 13:35
общий
Вообще-то, 2.25 - 1.75 = 0.5
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
15.04.2013, 13:40
общий
Да, это если считать по математическим правилам, а если программой, то выдает этот результат

-1,75
movl pA,0bfh
movl mAH,0f0h
movl mAL,00h

+2,25
movl pB,40h
movl mBH,10h
movl mBL,00h

Ответ 3E C0 00
Неизвестный
15.04.2013, 13:52
общий
15.04.2013, 13:53
Понял, это моя ошибка...

Считает правильно. Буду разбираться в самой программе. Пока вопросов нет) Спасибо большое!

Много чего от этого примера узнал :)
давно
Посетитель
7438
7205
15.04.2013, 14:00
общий
15.04.2013, 14:06
Ну тогда скажу Вам, что нормально!
Действительно, 0bfh,0f0h,00h + 40h,10h,00 = 3eh,0c0h,00 = 0.375
Но! Вы складываете совершенно другие числа! 0bfh,0f0h,00h = -1.875, а не -1.75
Правильно 0bfh,0e0h,00h ! Проверьте!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа