PDA

Просмотр полной версии : AVR studio вычитает не правильно.



Ярослав
29.03.2012, 14:54
Всем здравствуйте. У меня такая головоломка. Программирую я на AVR studio пишу программа на языке асемблера. Пишу программу для Attiny 2313. Но не могу понять. Когда вычитаю один регистр из другого то регистр SREG показывает, что получился отрицательный результат. Но как так то?? вот пример
ldi R16, 200
ldi R17, 5
sub loop1, loop2
.........
И после выполнения последней строчки, в регистре SREG выскакивает флаг отрицательного значения. 2 - бит. Хотя в регистре r16 стоит число после вычитания 195. Вроде верно. Но регистр АЛУ думает, что получился отрицательный результат. Почему.
Программировал сперва на работе, когда стало так получатся подумал что комп гонит. Повторил дома, тоже самое. Как правильно вычитать в микроконтроллере ? Буду признателен кто объяснит.

rx3apf
29.03.2012, 15:00
Всем здравствуйте. У меня такая головоломка. Программирую я на AVR studio пишу программа на языке асемблера. Пишу программу для Attiny 2313. Но не могу понять. Когда вычитаю один регистр из другого то регистр SREG показывает, что получился отрицательный результат. Но как так то?? вот пример
ldi R16, 200
ldi R17, 5
sub loop1, loop2
..........
И после выполнения последней строчки, в регистре SREG выскакивает флаг отрицательного значения. 2 - бит. Почему.
Программировал сперва на работе, когда стало так получатся подумал что комп гонит. Повторил дома, тоже самое. Как правильно вычитать в микроконтроллере ? Буду признателен кто объяснит.

Экстрасенсы в отпуске, а без них никак не догадаться, как выглядели .def для loop1 и loop2. Команда sub вычтет значение регистра loop2 из регистра loop1, а уж кто из них кто, без листинга никак не угадать...

Ярослав
29.03.2012, 15:10
Да извиняюсь неправильно написал.
ldi R16, 200
ldi R17, 5
sub R16, R17
Тоесть да, я задаю значение регистру R16 -- 200 Потом регистру R17 цифру 5. Потом Даю команду вычитания sub R16, R17 (sub 200 - 5) далее все правильно в первом регистре остается уже обработанное значение 195 а во втором без изменения. НО так как дальше вся работа завязывается у меня на флаге 2 бита SREG то мне нужны от туда правдоподобные данные. А там Ложь. Он говорит что проделанная операция принесла отрицательный знак. :((( Моя задача разделить 200 на пять. Но он уже на первом шаге говорит, что далее делить некуда, все минус. Вот в чем соль.
Вот немного отрывков. Полный текст пугает
.include "tn2313def.inc"
.list
.def temp = r16
.def loop1 = r17
.def loop2 = r18
.cseg
.org 0



ldi loop1, 200
ldi loop2, 5
sub loop1, loop2

ur8us
29.03.2012, 15:30
А разве 195 - это не отрицательное число?

rx3apf
29.03.2012, 15:45
А разве 195 - это не отрицательное число?
Вот именно. Бит 2 SREG ("N") это копия старшего бита результата. Т.е. числа в диапазоне 128..255 - отрицательные в таком понимании.

Для деления надо использовать флаг C (есть заем или нет заема).

Ярослав
29.03.2012, 15:54
Хороше попробую. А почему 128 по 255 для него отрицательные значения? Понимаю это азы, но я не знаю ни чего про это :((

R2DNU
29.03.2012, 16:05
Как представляются отрицательные числа в assembler
http://controllersystems.co m/books/praktika_programmiro vaniya_atmel_avr/otricatelnye-chisla-v-mk.html

А проще это так, если старший бит (7-й) имеет значение 1, то это число отрицательное. И соответственно проц будет выставлять бит N в SREG в 1. А. число 200 в двоичном виде имеет вид 11001000.
Для примера бит N SREG будет выставляться и в случае сложения, если при этом произойдет выставление в 1 старшего бита.
Попробуй это проверить сам

ldi loop1, 0x7b
ldi loop2, 0x05
add loop1,loop2

Ярослав
29.03.2012, 16:05
Извиняюсь. Глюки. Да еще в новой студии не могу найти развертку регистров. :(( Где они?

ur8us
29.03.2012, 16:08
А вот здесь все подробно описано: Дополнительный код (представление числа) (http://ru.wikipedia.org/wiki/%D0%94%D0%BE%D0%BF%D 0%BE%D0%BB%D0%BD%D0% B8%D1%82%D0%B5%D0%BB %D1%8C%D0%BD%D1%8B%D 0%B9_%D0%BA%D0%BE%D0 %B4_%28%D0%BF%D1%80% D0%B5%D0%B4%D1%81%D1 %82%D0%B0%D0%B2%D0%B B%D0%B5%D0%BD%D0%B8% D0%B5_%D1%87%D0%B8%D 1%81%D0%BB%D0%B0%29) .

R2DNU
29.03.2012, 16:36
В меню View -> Toolbars -> выставить галку около I/O и откроется (только при симуляции) окно I/O View в котором весь проц выводится.

ut1wpr
29.03.2012, 16:36
А вот здесь все подробно описано: Дополнительный код (представление числа) (http://ru.wikipedia.org/wiki/Дополнительный_код_( представление_числа) ) .Денис, приветище! Очень рад видеть!

R2DNU
29.03.2012, 16:57
А вот простой пример деления
tret:
sub loop1, loop2;вычитание
brcs yrte ;был перенос?
inc r16 ;не был, увеличение на 1 частного
rjmp tret ;вычитать еще раз
add loop1,loop2 ;вычисление остатка

в итоге в temp частное, в loop1 остаток деления.

Ярослав
29.03.2012, 17:58
Тем не менее всем спасибо за ответы. Не ожидал я конечно такого. Но все понял. Еще правда у меня один вопрос. В новой версии AVR Studio во время выполнения пошаговой операции debug не могу найти в окошечке состояние регистров. Раньше было (лет три назад) можно было посмотреть содержание любого регистра. От 1 - по последний. Щас там только служебные регистры, а где R1? R16 R20 ?? МОжет кто подскажет как открыть такую иконку.

Ярослав
31.03.2012, 14:00
А как сбрасывать счетные регистры 16 разрядного таймера счетчика по нулям? Кто ни будь знает?? Например мне надо засечь время между двумя импульсами или даже тремя, а он считает не сбрасываясь. Помогите пожалуйста.

rx3apf
01.04.2012, 12:46
А как сбрасывать счетные регистры 16 разрядного таймера счетчика по нулям? Кто ни будь знает?? Например мне надо засечь время между двумя импульсами или даже тремя, а он считает не сбрасываясь. Помогите пожалуйста.
А зачем для этого сбрасывать таймер ? Достаточно извлечь текущее его содержимое и где-нибудь сохранить, а потом вычесть из нового значения. Но в любом случае, и запись (обнуление), и чтение 16-битных таймеров происходит одномоментно (в отличии, скажем, от PIC16). старший байт значения автоматически фиксируется в специальном временном регистре. Это вполне понятно расписано в даташите.