Сворачиванием констант

qRoC
Offline
Зарегистрирован: 05.11.2011

Добрый день.

 

Разрабатывал простенький проект для arduino ( использую их ide ). В коде было уравнение в котором было умножение больших константных чисел. Проблему заметил когда уравнение показало неверный результат. По идее данное умножение должно было происходить на стадии компиляции. Залез в исходники ide - avr-gcc вызывается с параметром -Os, сворачивание констант должно происходить. Что не так?

step962
Offline
Зарегистрирован: 23.05.2011

qRoC пишет:

 Что не так?

Не так что?

Где пример неправильного результата?

Где мне взять столько кофейной гущи, чтобы нагадать, что вы там наворотили в своем простеньком проекте?

Показали хотя бы, что за большие константы у вас и что за действия над ними выполняются.

А то: 

"уважаемые ученые, у меня в подвале происходит стук. Объясните природу его образования"

qRoC
Offline
Зарегистрирован: 05.11.2011

 

qRoC пишет:

умножение больших константных чисел

 

int a = 6000 * 1000

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Читайте про типы данных. У Вас имеет место переполнение типа. Целочисленные типы - это не только int (который, кстати, позволяет хранить числа только диапазона +-32000). Константы тоже имеют тип. Например, 6000000L

2 admin: что-то в таблице символов не нашел "плюс-минус", раньше он там был :(

qRoC
Offline
Зарегистрирован: 05.11.2011

Я вам одно - вы мне другое

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

qRoC пишет:

 

qRoC пишет:

умножение больших константных чисел

 

int a = 6000 * 1000

Где другое?

Это присвоение НЕКОРРЕКТНО!

Нужно:

long a = 6000 * 1000

qRoC
Offline
Зарегистрирован: 05.11.2011

Вы понимаете суть самого топика?

qRoC
Offline
Зарегистрирован: 05.11.2011

Если Вам станет легче - я изменю пример:

int32_t b = 6000 * 1000;

 

Суть не меняет, при компиляции умножение не происходит.

step962
Offline
Зарегистрирован: 23.05.2011

qRoC пишет:

Вы понимаете суть самого топика?

А вот стоит более подробно расписать - и даже вам станет понятна суть вашего топика:

int32_t bad=6000*1000;
long good=6000L*1000L; // хотя можно и int32_t
int i=6000L*1000L;

void setup() {
  Serial.begin(9600);
  Serial.print("bad="); Serial.println(bad);  
  Serial.print("good="); Serial.println(good);  
  Serial.print("i="); Serial.println(i);  
}

void loop() {
}

Вывод:
bad=-29312
good=6000000
i=-29312

Ы?

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

У меня все происходит:


long a;

void setup()
{
  a=6000*2000;
}

void loop()
{
  a++;
}

Вот результат:

---- sketch_nov20a.ino ----------------------------------------------------------------------------
4:        void setup()
+00000093:   E080        LDI       R24,0x00       Load immediate
+00000094:   E19B        LDI       R25,0x1B       Load immediate
+00000095:   E0A0        LDI       R26,0x00       Load immediate
+00000096:   E0B0        LDI       R27,0x00       Load immediate
+00000097:   93800200    STS       0x0200,R24     Store direct to data space
+00000099:   93900201    STS       0x0201,R25     Store direct to data space
+0000009B:   93A00202    STS       0x0202,R26     Store direct to data space
+0000009D:   93B00203    STS       0x0203,R27     Store direct to data space
7:        }
+0000009F:   9508        RET                      Subroutine return

 

step962
Offline
Зарегистрирован: 23.05.2011

1) в правой части строки 5 все же нужен модификатор длинного целого (6000L либо 2000L, ну или оба сразу). иначе будет происходить перемножение по типу int.

2) а где в ассемблерном листинге собственно операция перемножения? неужто оптимизировалась?

(6000*2000=12000000 => 0x00B71B00, а, согласно приведенному листингу, в регистры, а из них в RAM загружается число 0x00001B00, т.е. 6912)

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Да. Про модификаторы я и сам забыл. Но смысл был в том, что это умножение делается на стадии прекомпиляции и в листинг попадает только результат. При уножении компилятор поместил результат там где-то у себя в 2 байта (int) и старшая часть результата (00B7) просто обрезалась. Вопрос был изначально про "почему у меня компилятор не считает". А листингов, подтверждающих то, что он не считает, не было.

Вот я и привел доказательство, что подобные вычисления производятся ДО компиляции и в код не попадают (это не оптимизация даже). Так что

qRoC пишет:

Если Вам станет легче - я изменю пример:

int32_t b = 6000 * 1000;

 

Суть не меняет, при компиляции умножение не происходит.

считаю голословным и неверным.

qRoC
Offline
Зарегистрирован: 05.11.2011

AlexFisher пишет:

Вот я и привел доказательство, что подобные вычисления производятся ДО компиляции и в код не попадают (это не оптимизация даже).

 

Это и так было ясно

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Тогда что не ясно?

Borland
Offline
Зарегистрирован: 17.05.2012

AlexFisher, пардонствую за бестактный вопрос, как мне получить ассемблерный код

 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Borland пишет:

AlexFisher, пардонствую за бестактный вопрос, как мне получить ассемблерный код

 

1. Находите файлы hex и cof во временном каталоге системы (можно в IDE включить вывод подробностей при компиляции - он сам скажет, куда эти файлы положил)

2. Открываете cof с помощью AVR Studio, отвечаете на вопрос об используемом процессоре соответственно плате (у меня это atmega2560 - arduino MEGA)

3. Он еще спросит, где файл с исходником - указываете на Ваш файл с исходником)

4. Включаете окно дизасемблера. Можете шагать :) И вообще, можно делать отладку.

Borland
Offline
Зарегистрирован: 17.05.2012

Обалдеть, а я дурак мучаюсь)))

Прерывания, порос портов  тоже можно симулировать?