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

 
 
 
Reply to this topicStart new topic
> Код на Си в два раза больше чем на ASM. Attiny2313, Много rjmp в дизассемблерном коде на Си
aivs
сообщение Mar 12 2013, 22:34
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Mar 12 2013, 22:40
Сообщение #2


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (aivs @ Mar 13 2013, 07:34) *
Меня интересует, что это за множество переходов в начале, для чего их делает компилятор?

Похоже на таблицу векторов прерываний.
З.Ы. Компилировать лучше с использованием специального скрипта - Makefile. Редко компилятору нужно задавать менее двух - трех ключей. Следовательно их много, и проще воспользоваться предназначенным для этого файлом, где все это удобно и четко прописано. Оптимизации в подавляющем большинстве достаточно -Os. Возможно она удалит неиспользуемую таблицу векторов.


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
arttab
сообщение Mar 13 2013, 00:59
Сообщение #3


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

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



а если еще оптимизацию по размеру включить...


--------------------
OrCAD, Altium,IAR, AVR....
Go to the top of the page
 
+Quote Post
Палыч
сообщение Mar 13 2013, 05:06
Сообщение #4


Гуру
******

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



Цитата(haker_fox @ Mar 13 2013, 02:40) *
Похоже на таблицу векторов прерываний. ... Возможно она удалит неиспользуемую таблицу векторов.

Это таблица векторов прерываний и есть. Оптимизация не удалит строки в неиспользуемой части таблицы, поскольку это - своеобразная защита "от дурака" на случай если программист случайно разрешит какое-либо прерывание, а соответствующий обработчик написать забудет.
Конечно, при столь маленькой программе "лишние" несколько десятков байт в программе "смотрятся" несколько удивительно, но:
1. При "нормальной" программе эти "лишние" байты - капля в море.
2. Программа на языке высокого уровня при любой оптимизации будет несколько "хуже" программы на ассемблере. Но время на разработку, отладку и сопровождение ПО уменьшается в разы. Отдельные части программы можно написать и на ассемблере (если это необходимо).
Go to the top of the page
 
+Quote Post
aivs
сообщение Mar 13 2013, 07:14
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 114
Регистрация: 3-10-09
Пользователь №: 52 731



То что код на Си всегда будет больше чем на ассемблере это понятно.
Конкретно эту таблицу векторов прерываний как удалить из этой прошраммы?
Или если дайте почитать про так написать Makefile с нужными опциМи компиляции.
Свои примеры приветствуются!

Сообщение отредактировал aivs - Mar 13 2013, 07:15
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 13 2013, 07:26
Сообщение #6


Гуру
******

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



QUOTE (aivs @ Mar 13 2013, 09:14) *
Конкретно эту таблицу векторов прерываний как удалить из этой программы?

1)Взять тут файл стартапа.
2)Отредактировать его, выкинув лишнее.
3)Ассемблировать.
4)Слинковать с основным модулем добавив линкеру ключ -nostartfiles.
5)Немного дописать основную программу
6)Убить кучу времени пытаясь понять, почему она перестала работать
7)Понять, что в п.2 удалили лишнее sm.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Mar 13 2013, 09:06
Сообщение #7


неотягощённый злом
******

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



Цитата(Сергей Борщ @ Mar 13 2013, 11:26) *
+1
Сейчас как раз идёт активное обсуждение добавления нового ключика к компилятору чтобы он сам использовал свободные вектора под код или данные для своего усмотрения.
Есть даже нечто рабочее в виде патча. Но до коммита в транк ещё видимо очень далеко.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Ruslan1
сообщение Mar 13 2013, 09:33
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 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". Так оно иногда такие хитрые финты выкидывает по многократному использованию кода, что в здравом уме на ассме долго думать придется чтобы такой компактности достичь sm.gif
Про "в разы меньше времени на Си чем на ассме"- это Вы не правы. Не в разы, а в тысячи и миллионы раз легче, особенно если речь идет о сопровождении (Само собой, я не говорю о лампочке).
Go to the top of the page
 
+Quote Post
aivs
сообщение Mar 13 2013, 12:13
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 114
Регистрация: 3-10-09
Пользователь №: 52 731



Оптимизация ради обучения, цель - знания.
Go to the top of the page
 
+Quote Post
SyncLair
сообщение Mar 13 2013, 15:22
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 209
Регистрация: 6-01-12
Пользователь №: 69 197



Цитата(Сергей Борщ @ Mar 13 2013, 11:26) *
1)Взять тут файл стартапа.
2)Отредактировать его, выкинув лишнее.
3)Ассемблировать.
4)Слинковать с основным модулем добавив линкеру ключ -nostartfiles.
5)Немного дописать основную программу
6)Убить кучу времени пытаясь понять, почему она перестала работать
7)Понять, что в п.2 удалили лишнее sm.gif

biggrin.gif полностью поддерживаю, особенно пункт 7 вас должен натокнуть на мысль о том что не стоит оптимизировать что-либо пока вы не достигли размера flash. Вам для чего выйгрыш в нескольких десятках байт?


--------------------
Go to the top of the page
 
+Quote Post
vvs157
сообщение Mar 13 2013, 17:59
Сообщение #11


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

Группа: Свой
Сообщений: 1 526
Регистрация: 8-04-05
Пользователь №: 3 960



Цитата(Ruslan1 @ Mar 13 2013, 12:33) *
а в тысячи и миллионы раз легче, особенно если речь идет о сопровождении (Само собой, я не говорю о лампочке).
То есть Вы утверждаете, что потратите час на написание или сопровожддение некого кода на С, а тот же код на асме (применительно к 8 бит Атмелу, а не GUI или СУБД больших машинах) будет отработан за 10е6 часов то есть 114 лет? Что-то неверится. Применительно к "мелким" 8 бит МК может и не нескольких раз не набраться.
Go to the top of the page
 
+Quote Post
adnega
сообщение Mar 13 2013, 18:11
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 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 дружественнее...
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Mar 13 2013, 18:21
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(SyncLair @ Mar 13 2013, 17:22) *
пункт 7 вас должен натокнуть на мысль о том что не стоит оптимизировать что-либо пока вы не достигли размера flash.

Не стоит отпимизировать...
Гораздо лучше вести проект с выключенной оптимизацией и когда он достигнет размера flash (килобайт 100-200) вдруг возникнет необходимость ещё в десятке-другом кБ, а его и нет...
И вы окажетесь с проектом на несколько десятков тысяч строк кода, который неизвестно как себя поведёт при включённой оптимизации.
Go to the top of the page
 
+Quote Post
arttab
сообщение Mar 14 2013, 01:59
Сообщение #14


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

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



оптимизация на С, С++ дает хорошую экономию места, но некоторые места (например дрыганье выводами) приходиться "защищать" от оптимизации, иначе компилятор может выкинуть часть кода.

с ассемблерном много возни, особенно на переходы с близких на дальние.
были проекты до 8К асм с каруселькой на 7 процессов

Итого: если плохо знаешь свой инструментарий, то будет плохо, иначе наоборот


--------------------
OrCAD, Altium,IAR, AVR....
Go to the top of the page
 
+Quote Post
MaxiMuz
сообщение Apr 23 2013, 19:12
Сообщение #15


Местный
***

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



Цитата(Ruslan1 @ Mar 13 2013, 12:33) *
Например, у компиляторов есть такая интересная оптимизация как "Procedural Abstraction". Так оно иногда такие хитрые финты выкидывает по многократному использованию кода, что в здравом уме на ассме долго думать придется чтобы такой компактности достичь sm.gif

а можно про эту штуку поподробнее ?
есть ли она на avr-gcc и если да, то где она включается ?
Спасибо)
Go to the top of the page
 
+Quote Post

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

 


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


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