|
|
  |
Код на Си в два раза больше чем на ASM. Attiny2313, Много rjmp в дизассемблерном коде на Си |
|
|
|
Mar 12 2013, 22:34
|
Частый гость
 
Группа: Участник
Сообщений: 114
Регистрация: 3-10-09
Пользователь №: 52 731

|
Написал тестовую программу на Ассемблере и Си для Attiny2313. Программа элементарна, при нажатии на кнопку загорается светодиод, при отпускании гасится. Вот код на ассемблере: Код ;########################################## ;## Нажатие на кнопку включает светодиод ## ;##########################################
.include "/usr/share/avra/includes/tn2313def.inc" ; Подключаем файл описаний .list ; Включаем листинг
.def temp = R16 ; Определение главного рабочего регистра
.cseg ; Выбор сегмента программного кода .org 0 ; Установка текущего адреса на 0 ldi temp, RAMEND ; Записываем адрес вершины стека в регистр temp out SPL, temp ; Записываем адрес вершины стека из регистра temp в регистр стека
ldi temp, 0 ; Записываем 0 в регистр temp out DDRD, temp ; Записываем 0 из регистра temp в DDRD (порт PD на ввод - кнопка) ldi temp, 0b11111111; Записываем 11111111 в регистр temp out DDRB, temp ; Записываем 11111111 из регистра temp в DDRB (порт PB на вывод - LED)
out PORTB, temp ; Записываем 11111111 из temp в PORTB (тушим светодиод) out PORTD, temp ; Записываем 11111111 из temp в PORTD (включаем внутр. резистры)
;--------------- Основной цикл ---------------------;
main: in temp, PIND ; Читаем содержимое порта PD out PORTB, temp ; Записываем содержимое temp в порт PB rjmp main ; Переход к началу программы Затем я дизассемблирил HEX файл, получился точно такой же код: Код 00000000 <.sec1>: 0: 0f ed ldi r16, 0xDF ; 223 2: 0d bf out 0x3d, r16 ; 61 4: 00 e0 ldi r16, 0x00 ; 0 6: 01 bb out 0x11, r16 ; 17 8: 0f ef ldi r16, 0xFF ; 255 a: 07 bb out 0x17, r16 ; 23 c: 08 bb out 0x18, r16 ; 24 e: 02 bb out 0x12, r16 ; 18 10: 00 b3 in r16, 0x10 ; 16 12: 08 bb out 0x18, r16 ; 24 14: fd cf rjmp .-6 ; 0x10 Вот код на Си: Код /**************************************** * Prog1.c * Нажатие на кнопку включает светодиод ****************************************/
#include <avr/io.h> #include <avr/iotn2313.h>
void main(void) { DDRB = 0b11111111; // Во всех разрядах регистра DDRB единицы --> все разряды PB работают на вывод (LED) PORTB = 0b11111111; // Во всех разрядах PB единицы и все разряды регистра DDRB работаю на вывод --> тушим Led DDRD = 0b00000000; // Во всех разрядах регистра DDRD нули --> все разряды PD работают на ввод (кнопка) PORTD = 0b11111111; // Во всех разрядах PD единицы и все разряды регистра DDRD работаю на ввод --> подключаем внутренние резистры // Вечный цикл while (1) { PORTB = PIND; } } После дизассемблера вид такой: Код 00000000 <.sec1>: 0: 12 c0 rjmp .+36 ; 0x26 2: 17 c0 rjmp .+46 ; 0x32 4: 16 c0 rjmp .+44 ; 0x32 6: 15 c0 rjmp .+42 ; 0x32 8: 14 c0 rjmp .+40 ; 0x32 a: 13 c0 rjmp .+38 ; 0x32 c: 12 c0 rjmp .+36 ; 0x32 e: 11 c0 rjmp .+34 ; 0x32 10: 10 c0 rjmp .+32 ; 0x32 12: 0f c0 rjmp .+30 ; 0x32 14: 0e c0 rjmp .+28 ; 0x32 16: 0d c0 rjmp .+26 ; 0x32 18: 0c c0 rjmp .+24 ; 0x32 1a: 0b c0 rjmp .+22 ; 0x32 1c: 0a c0 rjmp .+20 ; 0x32 1e: 09 c0 rjmp .+18 ; 0x32 20: 08 c0 rjmp .+16 ; 0x32 22: 07 c0 rjmp .+14 ; 0x32 24: 06 c0 rjmp .+12 ; 0x32 26: 11 24 eor r1, r1 28: 1f be out 0x3f, r1 ; 63 2a: cf ed ldi r28, 0xDF ; 223 2c: cd bf out 0x3d, r28 ; 61 2e: 02 d0 rcall .+4 ; 0x34 30: 09 c0 rjmp .+18 ; 0x44 32: e6 cf rjmp .-52 ; 0x0 34: 8f ef ldi r24, 0xFF ; 255 36: 87 bb out 0x17, r24 ; 23 38: 88 bb out 0x18, r24 ; 24 3a: 11 ba out 0x11, r1 ; 17 3c: 82 bb out 0x12, r24 ; 18 3e: 80 b3 in r24, 0x10 ; 16 40: 88 bb out 0x18, r24 ; 24 42: fd cf rjmp .-6 ; 0x3e 44: f8 94 cli 46: ff cf rjmp .-2 ; 0x46 Меня интересует, что это за множество переходов в начале, для чего их делает компилятор? Компилирую так: avr-gcc -O2 -Os -mmcu=attiny2313 -o Prog1.elf Prog1..c avr-objcopy -R .eeprom -O ihex Prog1.elf Prog1.hex
|
|
|
|
|
Mar 13 2013, 05:06
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(haker_fox @ Mar 13 2013, 02:40)  Похоже на таблицу векторов прерываний. ... Возможно она удалит неиспользуемую таблицу векторов. Это таблица векторов прерываний и есть. Оптимизация не удалит строки в неиспользуемой части таблицы, поскольку это - своеобразная защита "от дурака" на случай если программист случайно разрешит какое-либо прерывание, а соответствующий обработчик написать забудет. Конечно, при столь маленькой программе "лишние" несколько десятков байт в программе "смотрятся" несколько удивительно, но: 1. При "нормальной" программе эти "лишние" байты - капля в море. 2. Программа на языке высокого уровня при любой оптимизации будет несколько "хуже" программы на ассемблере. Но время на разработку, отладку и сопровождение ПО уменьшается в разы. Отдельные части программы можно написать и на ассемблере (если это необходимо).
|
|
|
|
|
Mar 13 2013, 07:26
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (aivs @ Mar 13 2013, 09:14)  Конкретно эту таблицу векторов прерываний как удалить из этой программы? 1)Взять тут файл стартапа. 2)Отредактировать его, выкинув лишнее. 3)Ассемблировать. 4)Слинковать с основным модулем добавив линкеру ключ -nostartfiles. 5)Немного дописать основную программу 6)Убить кучу времени пытаясь понять, почему она перестала работать 7)Понять, что в п.2 удалили лишнее
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Mar 13 2013, 09:06
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Сергей Борщ @ Mar 13 2013, 11:26)  +1 Сейчас как раз идёт активное обсуждение добавления нового ключика к компилятору чтобы он сам использовал свободные вектора под код или данные для своего усмотрения. Есть даже нечто рабочее в виде патча. Но до коммита в транк ещё видимо очень далеко.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Mar 13 2013, 09:33
|
Гуру
     
Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025

|
Цитата(aivs @ Mar 13 2013, 00:34)  Написал тестовую программу на Ассемблере и Си для Attiny2313. Программа элементарна, при нажатии на кнопку загорается светодиод, при отпускании гасится. Вот код на ассемблере: ..... Затем я дизассемблирил HEX файл, получился точно такой же код: .... Для начала, нужно вернуться к истокам и разобраться, почему "Дизасемблированный HEX файл" из "программы на Ассемблере" дает "точно такой же код". После этого нужно ответить на вопрос, почему дизассемблированный HEX файл, полученный в результате компиляции из C, содержит другие команды чем исходный Си текст. И только после этого можно приступать к решению проблемы, которую Вы подняли. Это базовые знания. Без этого понимания сложно что-то делать. Повторять чужое-можно, делать свое хорошего качества и понимать почему результат такой- не получится. Кстати, еще полезно задуматься о том, а зачем Вам эта оптимизация по размеру? как самоцель? Оптимизация должна быть аргументированная и производиться с какой-то целью (например, для достижения необходимой скорости реакции, времени выполнения, размера программы). Просто так оптимизировать чтобы было оптимально- это бесконечный и никому не нужный процесс. Цитата(Палыч @ Mar 13 2013, 07:06)  2. Программа на языке высокого уровня при любой оптимизации будет несколько "хуже" программы на ассемблере. Но время на разработку, отладку и сопровождение ПО уменьшается в разы. Отдельные части программы можно написать и на ассемблере (если это необходимо). Например, у компиляторов есть такая интересная оптимизация как "Procedural Abstraction". Так оно иногда такие хитрые финты выкидывает по многократному использованию кода, что в здравом уме на ассме долго думать придется чтобы такой компактности достичь  Про "в разы меньше времени на Си чем на ассме"- это Вы не правы. Не в разы, а в тысячи и миллионы раз легче, особенно если речь идет о сопровождении (Само собой, я не говорю о лампочке).
|
|
|
|
|
Mar 13 2013, 15:22
|
Местный
  
Группа: Свой
Сообщений: 209
Регистрация: 6-01-12
Пользователь №: 69 197

|
Цитата(Сергей Борщ @ Mar 13 2013, 11:26)  1)Взять тут файл стартапа. 2)Отредактировать его, выкинув лишнее. 3)Ассемблировать. 4)Слинковать с основным модулем добавив линкеру ключ -nostartfiles. 5)Немного дописать основную программу 6)Убить кучу времени пытаясь понять, почему она перестала работать 7)Понять, что в п.2 удалили лишнее   полностью поддерживаю, особенно пункт 7 вас должен натокнуть на мысль о том что не стоит оптимизировать что-либо пока вы не достигли размера flash. Вам для чего выйгрыш в нескольких десятках байт?
--------------------
|
|
|
|
|
Mar 13 2013, 18:11
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(vvs157 @ Mar 13 2013, 21:59)  То есть Вы утверждаете, что потратите час на написание или сопровожддение некого кода на С, а тот же код на асме (применительно к 8 бит Атмелу, а не GUI или СУБД больших машинах) будет отработан за 10е6 часов то есть 114 лет? Что-то неверится. Применительно к "мелким" 8 бит МК может и не нескольких раз не набраться. Скорее так: нужно по-быстрому поменять несколько мест в нескольких программах (объемом 10К строк). Может алгоритм поменять, может тип данных, структурку и т.п. На C такие действия тривиальны, на ASM врагу не пожелаешь)) Да, и к Ctrl-C, Ctrl-V вариант C дружественнее...
|
|
|
|
|
Mar 14 2013, 01:59
|

Профессионал
    
Группа: Свой
Сообщений: 1 432
Регистрация: 7-12-04
Из: Новосибирск
Пользователь №: 1 371

|
оптимизация на С, С++ дает хорошую экономию места, но некоторые места (например дрыганье выводами) приходиться "защищать" от оптимизации, иначе компилятор может выкинуть часть кода.
с ассемблерном много возни, особенно на переходы с близких на дальние. были проекты до 8К асм с каруселькой на 7 процессов
Итого: если плохо знаешь свой инструментарий, то будет плохо, иначе наоборот
--------------------
OrCAD, Altium,IAR, AVR....
|
|
|
|
|
Apr 23 2013, 19:12
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658

|
Цитата(Ruslan1 @ Mar 13 2013, 12:33)  Например, у компиляторов есть такая интересная оптимизация как "Procedural Abstraction". Так оно иногда такие хитрые финты выкидывает по многократному использованию кода, что в здравом уме на ассме долго думать придется чтобы такой компактности достичь  а можно про эту штуку поподробнее ? есть ли она на avr-gcc и если да, то где она включается ? Спасибо)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|