реклама на сайте
подробности

 
 
5 страниц V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> Сопоставление проектов С и АСМ, Немного цифр
singlskv
сообщение Feb 21 2008, 17:49
Сообщение #31


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(_Pasha @ Feb 21 2008, 19:57) *
Код
void EE_Proof_Write_Block(const void *pointer_ram,
              void *pointer_eeprom,
              size_t n)
{
size_t j;
uint8_t *src,*dst;

src = (uint8_t*)pointer_ram;
dst = (uint8_t*)pointer_eeprom;

for (j=0;j<n;j++)
{
  if (eeprom_read_byte(dst) != *src)
      eeprom_write_byte(dst,(uint8_t)*src);
  dst++;
  src++;
}
return;
}

Несколько моментов про Ваш код:
- вместо цикла for лучше использовать do..while c проверкой size_t n == 0 только в самом начале..
- написав отдельно src++ и вызывая стандартные функции Вы сами себя лишили возможности
пользоваться автоинкрементом при доступе к данным в RAM
- каждая из функций eeprom_xxx будет ждать флага освобождения EEPROM
- каждая из функций eeprom_xxx будет прописывать один и тот же адрес в EEAR

попробуйте это отрихтовать и удивитесь лаконичности полученого кода...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 21 2008, 19:09
Сообщение #32


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(defunct @ Feb 21 2008, 14:52) *
стиль кода Вашего примера не Сишный, и рад что вышло.


Нашел. Это паскалевский стиль. Обнаружился древний, почти безусловный рефлекс: как только в программе забрезжит хоть какой-то намек на ввод-вывод, бежим как от огня от перечислительных типов. Применительно к "С" это распространилось и на битовые поля. Так что, могу на любом языке, как на паскале. smile.gif

Кстати, был еще один рефлекс: клавишу F2 нажимать каждые 15 секунд. Ох и долго избавлялся!

Цитата(singlskv @ Feb 21 2008, 20:49) *
Несколько моментов про Ваш код:

попробуйте это отрихтовать и удивитесь лаконичности полученого кода...

Спасибо! Рихтуем, удивляемся... smile.gif
Go to the top of the page
 
+Quote Post
singlskv
сообщение Feb 21 2008, 22:37
Сообщение #33


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(ReAl @ Feb 21 2008, 11:43) *
Ну извините... Так можно дойти до "а на асме я могу что-то другое делать, пока EEPROM пишется, а С-шная программа станет колом на всё время записи блока, во какой плохой язык С".
Вотъ, это тоже хотелось бы обсудить, хотя конкретно это, я уже пытался обсуждать,
но большинство опонентов высказалось в том смысле, что в IAR удобно обращаться к
таким(EEPROM) переменным и все тут...

А сейчас я вот задался интересным вопросом, если кто еще не заметил, в новых AVR (mega48/88/......)
есть такая фича, можно отдельно стирать ячейку и можно отдельно ее программировать...

Вопрос:
кто-нить уже пробовал записать в ячейку 2 раза без стирания ?
ИМХО, это открывает новые возможности для увеличения количества записи в eeprom,
но конечно, этот факт, требует дополнительной проверки, добровольцы есть ?
Go to the top of the page
 
+Quote Post
Artak
сообщение Feb 21 2008, 23:25
Сообщение #34


Участник
*

Группа: Свой
Сообщений: 41
Регистрация: 17-01-08
Пользователь №: 34 178



Ребята, может бить мой вопрос покажетса смехотwорным
но все- таки.
Если нужно умножить два восьмибитних числа и получить 16 битный результат достаточно написать
что то вроде
mul r16, r17 (конечно только для mega AVR)
и читать результат из пары r0,r1.
На C приходится писать
int result = (int)a * (int)b; или int result = (int)a * b; (a и b 8 битные)

Так как если написать int result = a * b то компилятор согласно правилам языка C сначала генерирует mul а потом обнуляет старший байт (результат умножения двух char получается в виде char и потом толко присвоивается int у)

А код скомплированный в результате int result = (int)a * (int)b; получаетса очень громоздкий, так как умножаяютса два 16 битных числа не обращая внимания на то что в старших байтах нули

чтобы решить проблему скорости мне пришлось в проекте написанном на C писать int result = a * b потом из сгенерированного асм листига вручную удалить clr r1 после mul-а и сгенерировать hex фаил в AVR Studio

А есть вообще грамотный способ решения таких проблем в C коде?

Сообщение отредактировал Artak - Feb 21 2008, 23:28
Go to the top of the page
 
+Quote Post
Rst7
сообщение Feb 22 2008, 06:29
Сообщение #35


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
А есть вообще грамотный способ решения таких проблем в C коде?


В IAR'е можете написать __multiply_unsigned( a , b ) - это непосредственно сгенерит mul. Для портабельности не забудьте на этапе компиляции проверить текущий процессор и компилятор, и если это не AVR и не IAR, сделать #define __multiply_unsigned(var1,var1) ((var1)*(var2)). Про остальные умножения можете прочитать в доке по IAR'у, ключевое слово "Intrinsic functions"


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Petka
сообщение Feb 22 2008, 07:25
Сообщение #36


Профессионал
*****

Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886



Цитата(singlskv @ Feb 22 2008, 01:37) *
Вопрос:
кто-нить уже пробовал записать в ячейку 2 раза без стирания ?
ИМХО, это открывает новые возможности для увеличения количества записи в eeprom,
но конечно, этот факт, требует дополнительной проверки, добровольцы есть ?


Велосипед уже изобретён. Atmel AN "AVR103"
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 22 2008, 07:41
Сообщение #37


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(singlskv @ Feb 21 2008, 20:49) *
Несколько моментов про Ваш код:
- вместо цикла for лучше использовать do..while c проверкой size_t n == 0 только в самом начале..
- написав отдельно src++ и вызывая стандартные функции Вы сами себя лишили возможности
пользоваться автоинкрементом при доступе к данным в RAM
- каждая из функций eeprom_xxx будет ждать флага освобождения EEPROM
- каждая из функций eeprom_xxx будет прописывать один и тот же адрес в EEAR

попробуйте это отрихтовать и удивитесь лаконичности полученого кода...


Поменял for() на while() и убрал лишнее копирование параметра size_t n . Т.е. while(n){}
Дальнейшее улучшение усиливает зависимость от железа, поэтому в данном случае (не библиотечном) не имеет смысла.
Бухгалтерия -12 байт. Итого в гору не более 24 байт на "крайне нежелательную" на первый взгляд функцию.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Feb 22 2008, 09:45
Сообщение #38


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Petka @ Feb 22 2008, 10:25) *
Велосипед уже изобретён. Atmel AN "AVR103"
Спасибо за наводку,
этот апликайшн как-то мимо меня пролетел...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 22 2008, 10:47
Сообщение #39


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Теперь про асм.
В контексте многопоточного программирования очень полезно использование итераторов.
Пример:
Код
Iterate_16:
; input xL:xH = counter
; zL:zH = pointer to procedure/iteration body
    push    zL
    push    zh

    push    xL
    push    xH
    icall
    pop    xH
    pop    xL

    sbiw    xL,1
    brne    iterate_16_1    

    pop    zh
    pop    zL
    ret    

iterate_16_1:
    push    xL
    push    xh
    leave(Iterate_16_2)

Iterate_16_2:
    pop    xh
    pop    xL
    pop    zh
    pop    zL
    rjmp    Iterate_16


Данный итератор позволяет создавать циклы произвольной вложенности (в зависимости от размеров стека Вашего процесса). При этом подпрограмма -тело цикла вызывается косвенно, и может быть как атомарной, так и передавать управление системе, т.к. все параметры цикла как конструкции находятся в локальном стеке процесса.
Пример применения:
Код
func1:
; blah,blah,blah
    ret    
;...................................
func2:
    ldi16    xL,xh,0x100
    ldi16    zL,zh,func1;  
    jmp    Iterate_16
;...................................
func3:
    ldi16    xL,xh,0x0010
    ldi16    zL,zh,func2
    jmp    Iterate_16


В приведенном примере внешний цикл описан в func3, в котором вызывается внутренний цикл, описанный func2. Примерный сишный эквивалент
Код
int i,j;
for(i=0x0010;i >= 0;i--)
  for(j=0x100;j>=0;j--) func1();

... но в условиях кооперативного распределения ресурсов

P.S. Исправил примеры func2, func3. Была ошибка в загрузке Z. Кому интересно, обратите внимание.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 22 2008, 15:27
Сообщение #40


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Artak @ Feb 22 2008, 01:25) *
На C приходится писать
int result = (int)a * (int)b; или int result = (int)a * b; (a и b 8 битные)
Так как если написать int result = a * b то компилятор согласно правилам языка C сначала генерирует mul а потом обнуляет старший байт (результат умножения двух char получается в виде char и потом толко присвоивается int у)
По стандарту языка С те два a,b обязаны быть приведены к int до выполнения команды умножения. Т.е. явне приведения не нужны, результат должен быть правильным. Иначе - в топку компилятор, С хорош стандартом, если для каждого компилятора надо менять привычки - то тогда проще на асме писать.

Цитата(Artak @ Feb 22 2008, 01:25) *
А код скомплированный в результате int result = (int)a * (int)b; получаетса очень громоздкий, так как умножаяютса два 16 битных числа не обращая внимания на то что в старших байтах нули
чтобы решить проблему скорости мне пришлось в проекте написанном на C писать int result = a * b потом из сгенерированного асм листига вручную удалить clr r1 после mul-а и сгенерировать hex фаил в AVR Studio


Код
#include <stdint.h>

uint16_t mul88(uint8_t a, uint8_t b)
{
    return a*b;
}


avr-gcc -O2 -S -mmcu=atmega8

Код
    .text
.global    mul88
    .type    mul88, @function
mul88:
/* prologue: frame size=0 */
/* prologue end (size=0) */
    mul r22,r24
    movw r24,r0
    clr r1
/* epilogue: frame size=0 */
    ret
Ну да, clr r1... Но уже после переноса результата умножения в пару R25:R24, так как по соглашениям avr-gcc регистр R1 содержит константу 0 (я бы предложил попробовать переделать это хозяйство на два временных регистра __tem_reg_l__, __temp_reg_h__ и R2 как константу 0, чтобы не мучиться каждый раз после умножения, но неизвестно, как занятие R2 скажется на остальном).


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 22 2008, 23:10
Сообщение #41


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



В общем, наигрался я с "С". Память заканчивается, а проект лежит. Теперь переписываю на асме. Размер кода обещает быть в 2 раза короче (к слову о больших проектах). Да и пишется все по-быстрому, если знаешь, что делаешь. После чего все эти компиляторы, расплодившиеся в последнее время у меня в компе, летят в корзину. То же самое, кстати, касается и pic18 и dspic30/33 и HCS08, коими я иногда страдаю. Компилятор-то, оказывается, в голове...
Go to the top of the page
 
+Quote Post
defunct
сообщение Feb 22 2008, 23:37
Сообщение #42


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(_Pasha @ Feb 23 2008, 01:10) *
В общем, наигрался я с "С". Память заканчивается, а проект лежит. Теперь переписываю на асме.

Совет для того чтобы память не заканчивалась в проектах на "C"
1. Делать стек большим, а глобальных переменных поменьше.
2. Использовать heap.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Feb 22 2008, 23:55
Сообщение #43


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(_Pasha @ Feb 23 2008, 02:10) *
В общем, наигрался я с "С". Память заканчивается, а проект лежит. Теперь переписываю на асме. Размер кода обещает быть в 2 раза короче (к слову о больших проектах).

Такая разница может получиться ТОЛЬКО на вычислительных алгоритмах и в основном
в местах где при использовании С необходимо делать преобразование типов,
ну или для вариантов когда просто в С нет соответствующего размера типа,
например в С нет 3-байтовых переменных...

Для остальных вариантов..., ну показывайте код что ли, думаю что после некоторой оптимизации
он Вас опять же сможет удивить...


Цитата(defunct @ Feb 23 2008, 02:37) *
Совет для того чтобы память не заканчивалась в проектах на "C"
1. Делать стек большим, а глобальных переменных поменьше.
2. Использовать heap.
Вот здесь хотелось бы разъяснений и поподробнее...(без подколок...),
я не понимаю как уменьшить количество глобальных переменных.
Я не понимаю как можно использовать heap для уменьшения расхода памяти вместо
использования глобальных переменных...
Go to the top of the page
 
+Quote Post
Alex B._
сообщение Feb 23 2008, 00:03
Сообщение #44


Знающий
****

Группа: Свой
Сообщений: 943
Регистрация: 6-07-04
Из: Санкт-Петербург
Пользователь №: 274



Цитата(singlskv @ Feb 23 2008, 02:55) *
я не понимаю как уменьшить количество глобальных переменных.
Я не понимаю как можно использовать heap для уменьшения расхода памяти вместо
использования глобальных переменных...

хм, а чего тут не понятного? sad.gif
Go to the top of the page
 
+Quote Post
singlskv
сообщение Feb 23 2008, 00:08
Сообщение #45


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Alex B._ @ Feb 23 2008, 03:03) *
хм, а чего тут не понятного? sad.gif
Содержательный ответ, а примерчик не подкините ?
Go to the top of the page
 
+Quote Post

5 страниц V  < 1 2 3 4 5 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 12:17
Рейтинг@Mail.ru


Страница сгенерированна за 0.01576 секунд с 7
ELECTRONIX ©2004-2016