|
|
  |
Сопоставление проектов С и АСМ, Немного цифр |
|
|
|
Feb 21 2008, 17:49
|
дятел
    
Группа: Свой
Сообщений: 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 попробуйте это отрихтовать и удивитесь лаконичности полученого кода...
|
|
|
|
|
Feb 21 2008, 19:09
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(defunct @ Feb 21 2008, 14:52)  стиль кода Вашего примера не Сишный, и рад что вышло. Нашел. Это паскалевский стиль. Обнаружился древний, почти безусловный рефлекс: как только в программе забрезжит хоть какой-то намек на ввод-вывод, бежим как от огня от перечислительных типов. Применительно к "С" это распространилось и на битовые поля. Так что, могу на любом языке, как на паскале.  Кстати, был еще один рефлекс: клавишу F2 нажимать каждые 15 секунд. Ох и долго избавлялся! Цитата(singlskv @ Feb 21 2008, 20:49)  Несколько моментов про Ваш код:
попробуйте это отрихтовать и удивитесь лаконичности полученого кода... Спасибо! Рихтуем, удивляемся...
|
|
|
|
|
Feb 21 2008, 22:37
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(ReAl @ Feb 21 2008, 11:43)  Ну извините... Так можно дойти до "а на асме я могу что-то другое делать, пока EEPROM пишется, а С-шная программа станет колом на всё время записи блока, во какой плохой язык С". Вотъ, это тоже хотелось бы обсудить, хотя конкретно это, я уже пытался обсуждать, но большинство опонентов высказалось в том смысле, что в IAR удобно обращаться к таким(EEPROM) переменным и все тут... А сейчас я вот задался интересным вопросом, если кто еще не заметил, в новых AVR (mega48/88/......) есть такая фича, можно отдельно стирать ячейку и можно отдельно ее программировать... Вопрос: кто-нить уже пробовал записать в ячейку 2 раза без стирания ? ИМХО, это открывает новые возможности для увеличения количества записи в eeprom, но конечно, этот факт, требует дополнительной проверки, добровольцы есть ?
|
|
|
|
|
Feb 22 2008, 10:47
|
;
     
Группа: Участник
Сообщений: 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. Кому интересно, обратите внимание.
|
|
|
|
|
Feb 22 2008, 15:27
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 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 скажется на остальном).
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Feb 22 2008, 23:10
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
В общем, наигрался я с "С". Память заканчивается, а проект лежит. Теперь переписываю на асме. Размер кода обещает быть в 2 раза короче (к слову о больших проектах). Да и пишется все по-быстрому, если знаешь, что делаешь. После чего все эти компиляторы, расплодившиеся в последнее время у меня в компе, летят в корзину. То же самое, кстати, касается и pic18 и dspic30/33 и HCS08, коими я иногда страдаю. Компилятор-то, оказывается, в голове...
|
|
|
|
|
Feb 22 2008, 23:55
|
дятел
    
Группа: Свой
Сообщений: 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 для уменьшения расхода памяти вместо использования глобальных переменных...
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|