|
STM32 Ассемблер. Идеи и приёмы написания, Правила хорошего тона и макросы |
|
|
|
Jan 15 2014, 22:50
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
По ассемблеру для арм документации и разного рода примеров гораздо меньше для С. Начал осваивать и возникли сомнения, правильный ли подход частого использования макросов и где та грань, свыше которой не стоит заморачиваться с написанием кода. В ассемблера я не силён, в основном по-любительски пишу на С. Но вот раз начал осваивать асм, сделал несколько элементарных макросов для битовых операций, настройки и использования портов. Вопрос в том правильно ли это делать и использовать таким образом (когда в коде используются много макросов), или может быть есть более рациональный способ, как лучше писать на асме для арм. Вот примерчик: STM32F100RB. И что конкретно делает команда bfi R1,R2,#$Pin,#4 ? Определение макросов: Код ;-------------------------------------- ;Start_GPIO_Conf $Port,$PinRange - начало настройки порта, где $Port - имя порта (GPIOA,..), $PinRange - верхняя/нижняя тетрада порта (GPIO_CR_H/GPIO_CR_L) macro Start_GPIO_Conf $Port,$PinRange mov32 R0,#$Port ;загружаем в регистр "R0" имя порта (его код) из памяти ldr R1,[R0,#$PinRange];загружаем в регистр "R1" значение по адресу из памяти "R0 + #GPIO_CR_H(0x00)" или "R0 + #GPIO_CR_H(0x04)" mend ;-------------------------------------- ;GPIO_Conf $Pin,$Mode - настройка ножек выбраного порта, где $Pin - номер ножки (CNF_Pin_0,..), $Mode - режим ножки (GPIO_OUT_50_PP,..) macro PinConfig $Pin,$Mode movs R2,#$Mode bfi R1,R2,#$Pin,#4 mend ;-------------------------------------- ;End_GPIO_Conf $Port,$PinRange - конец настройки порта, где $Port - имя порта (GPIOA,..), $PinRange - верхняя/нижняя тетрада порта (GPIO_CR_H/GPIO_CR_L) macro End_GPIO_Conf $Port,$PinRange str R1,[R0,#$PinRange];загружаем в память по адресу "R0 + #GPIO_CR_H(0x00)" или "R0 + #GPIO_CR_H(0x04)" значение "R1" mend ;-------------------------------------- ;SetBit_GPIO $Port,$Pin macro SetBit_GPIO $Port,$Pin mov32 R0,#($Port + GPIO_BSRR) mov32 R1,#$Pin str R1,[R0] mend ;-------------------------------------- ;ResetBit_GPIO $Port,$Pin macro ResetBit_GPIO $Port,$Pin mov32 R0,#($Port + GPIO_BRR) mov32 R1,#$Pin str R1,[R0] mend ;-------------------------------------- Использование в программе: Код ;-------------------------------------- Start_GPIO_Conf GPIOC,GPIO_CR_H PinConfig CNF_Pin_9,GPIO_OUT_50_PP PinConfig CNF_Pin_8,GPIO_OUT_50_PP End_GPIO_Conf GPIOC,GPIO_CR_H ;-------------------------------------- SetBit_GPIO GPIOC,PIN9 SetBit_GPIO GPIOC,PIN8 ;-------------------------------------- Пробный проект в Keil 5 прикреплен:
Сообщение отредактировал allsettingsdone - Jan 15 2014, 22:55
|
|
|
|
|
Jan 16 2014, 01:58
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Все зависит от того чего вы хотите в итоге. Если вы упражняетесь смысл имеет. Если это коммерческий продукт убежден что не имеет. С темпами развития процессоров сейчас на первый план выход не отдельная производительность одной функции, а удобство поддержки, модификации и расширения программного решения. В том числе и перенос его на другие процессоры и платформы. А для этого чем более абстрактно написан код и чем более читаемо и понятно он написан тем лучше. код из раздела Код a = (!temp) ? 2 : 0; гораздо хуже чем код Код if(temp != 0) a = 2; else a = 0; и второй момент, Код SetBit_GPIO $Port,$Pin macro SetBit_GPIO $Port,$Pin mov32 R0,#($Port + GPIO_BSRR) mov32 R1,#$Pin str R1,[R0] mend каким образом вы будете гарантировать что в ходе выполнения вашей программы к моменту вызова этого макроса у вас свободны R0 и R1? То есть просто по ходу программы написанной на С этот макрос вызывать нельзя. А если вы будете следить за этими регистрами всю программу, то это как раз ярчайший пример АБСОЛЮТНО не поддерживаемого кода. Любое шевеление в будущем чревато багами.
|
|
|
|
|
Jan 16 2014, 05:38
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
Встраивать асемблеровский код в проект на С я не планирую, идея в написании всего проекта на асм, так что я условился приблизительно регистры R0-R3 использовать с оглядкой на то что они будут постоянно меняться, так как задействованы почти во всех макросах. А уже по ходу выполнения программы буду держать в поле зрения другие регистры с ключевой информацией. Вот ещё что интересно: одно и то же действие можно сделать разными командами и бывает не понятно как лучше поступить. Вот например загрузка в регистр адреса из памяти: (кусочек кода из макроса) Код mov32 R0,#$Port или Код ldr R0,=$Port В итоге эти две строчки равнозначны и вот какую из них лучше применять совсем непонятно. Хотелось бы узнать как бы идею и философию подхода к программированию на ассемблере для мк. (может есть годные примеры такого?) Встраивать асемблеровский код в проект на С я не планирую, идея в написании всего проекта на асм, так что я условился приблизительно регистры R0-R3 использовать с оглядкой на то что они будут постоянно меняться, так как задействованы почти во всех макросах. А уже по ходу выполнения программы буду держать в поле зрения другие регистры с ключевой информацией. Вот ещё что интересно: одно и то же действие можно сделать разными командами и бывает не понятно как лучше поступить. Вот например загрузка в регистр адреса памяти: (кусочек кода из макроса) Код mov32 R0,#$Port или Код ldr R0,=$Port В итоге эти две строчки равнозначны и вот какую из них лучше применять совсем непонятно. Или вот ещё Код mov32 R0,#($Port + GPIO_BSRR) Тоже интересно где именно происходит это сложение? Как я понимаю в на эту строчку уйдет далеко не два такта микроконтроллера? Хотелось бы узнать как бы идею и философию подхода к программированию на ассемблере для мк. (может есть годные примеры такого?) PS: с BFI разобрался
Сообщение отредактировал allsettingsdone - Jan 16 2014, 06:27
|
|
|
|
|
Jan 16 2014, 07:10
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Поддерживаю. Весь проект на ассемблере - это долго, опасно, и не эффективно, если конечно вы делаете не новогоднюю гирлянду с 2 режимами мигания.
Убейте книгой того кто вам сказал что крутые железячники все пишут на ассемблере, это было верно для готов 80. Сейчас уже давно и С++ практикуют, потому что стоимость машинного такта неуклонно падает. А требования к скорости и качеству разработки очень быстро растут.
Поглядите новым продуктам ставят сроки жизни и актуальности 4-5 лет. И если вы на ассемблере год будите писать программу, и год ее отлаживать, то через 2-3 оставшихся года при переходе на новый проц, вы что опять 2 года жизни прибора отъедите? Кому нужна такая разработка?
Максимум где допустим ассемблер - это вставки в особо критических местах кода, да и то в 95% случаев оптимизаторы современных языков делают эту работу лучше.
Не ходите валить лес с топором как делали наши деды, уже давно есть бензопилы!
|
|
|
|
|
Jan 16 2014, 07:40
|

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

|
Цитата(allsettingsdone @ Jan 16 2014, 00:50)  Использование в программе: Код ;-------------------------------------- SetBit_GPIO GPIOC,PIN9 SetBit_GPIO GPIOC,PIN8 ;-------------------------------------- Разворачиваем, получаем Код mov32 R0,#(GPIOC + GPIO_BSRR) mov32 R1,#PIN9 str R1,[R0] mov32 R0,#(GPIOC + GPIO_BSRR) mov32 R1,#PIN8 str R1,[R0] Дважды грузится R0 одинаковым значением. И где хваленый выигрыш от Ассемблера? Такого даже самый плохой Си-компилятор себе не позволяет. Не морочьте себе и нам голову, лучше потратьте это время и эти усилия на более глубокое изучение Си или Си с плюсами. Поверьте, это будет гораздо продуктивнее и полезнее. Ассемблер на уровне, достатотчном для анализа листингов и пошаговой отладки вы уже знаете.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 16 2014, 07:50
|

Частый гость
 
Группа: Свой
Сообщений: 115
Регистрация: 6-06-05
Из: Ukraine
Пользователь №: 5 764

|
Топикстартер задал конкретный вопрос в надежде получить от господ ПРОФЕССИОНАЛОВ конкретный ответ и если вы не можете его дать, то наверно лучше помолчать (наболело). Я для ARMов не программирую, но посоветовал бы глянуть книги на эту тему: 1. Joseph Yiu "The Definitive Guide to the ARM Cortex-M0" 2. Joseph Yiu "The Definitive Guide to the ARM Cortex-M3" 3. Vincent Mahout "Assembly Language Programming: ARM Cortex-M3" 4. Muhammad Ali Mazidi "ARM Assembly Language Programming & Architecture" 5. Jonathan Valvano "Embedded Systems: Introduction to Arm® Cortex-M Microcontrollers" Сайт автора книгиВсе эти книги содержат достаточно примеров на асме. Вот ссылка на реальный проект для Cortex-M0, я думаю если поискать, то можно много информации найти. Желаю удачи
|
|
|
|
|
Jan 16 2014, 08:18
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
Как раз читаю одну из этих книг. Что касается С, то на нем я как раз и пишу, но есть мнение что качественно и без извращений, писать на асм может дать выигрыш в прозрачности кода и более логически правильному её написанию и именно к микроконтроллерам это очень даже применимо. Я думаю что современный компилятор таки может гораздо лучше человека составить асм код, но когда пишешь на С, то не всегда очевидно какое огромное кол-во операций может повлечь за собой та или иная простенькая строчка на С.
Сообщение отредактировал allsettingsdone - Jan 16 2014, 08:24
|
|
|
|
|
Jan 16 2014, 09:57
|
Знающий
   
Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317

|
Цитата но когда пишешь на С, то не всегда очевидно какое огромное кол-во операций может повлечь за собой та или иная простенькая строчка на С. Вы всегда можете открыть листинги и посмотреть что сделал компилятор и подправить.
|
|
|
|
|
Jan 16 2014, 10:56
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
Ладно, а что по поводу таких вещей: Код mov32 R0,#($Port + GPIO_BSRR) Интересно, где именно происходит сложение "$Port + GPIO_BSRR" в данном случае $Port = 0x40001800, а GPIO_BSRR = 0x10. Для такой операции тоже ведь нужно использовать регистры, я пытался проследить этот момент, но именного таких чисел не увидел. И где вообще хранится константы когда мы используем их в виде "mov R0,#4" - вот число 4 здесь, процессор же должен от куда нибудь его взять? Откуда именно (если из ПЗУ, то как узнать по какому адресу компилятор что,где ложит)? Цитата(Golikov A. @ Jan 16 2014, 12:23)  ассемблер очевиднее С, только для ОЧЕНЬ маленьких программок из раздела мигаем лампочкой. Да и то С тут очевиднее... Любую программу же можно разбить на отдельные блоки/функции/файлы отвечающие за что-то одно. И можно будет во всем разобраться.
Сообщение отредактировал allsettingsdone - Jan 16 2014, 10:53
|
|
|
|
|
Jan 16 2014, 11:08
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(allsettingsdone @ Jan 16 2014, 14:18)  Как раз читаю одну из этих книг. Что касается С, то на нем я как раз и пишу, но есть мнение что качественно и без извращений, писать на асм может дать выигрыш в прозрачности кода и более логически правильному её написанию и именно к микроконтроллерам это очень даже применимо. Как правило, наоборот - чем код объёмнее - тем он менее прозрачен, а на асме код всяко будет ОБЪЁМНЕЕ  Цитата(allsettingsdone @ Jan 16 2014, 14:18)  Я думаю что современный компилятор таки может гораздо лучше человека составить асм код, Что-то очень часто приходится слышать это заблуждение.... По-моему пошло из рекламных буклетов си-компиляторов и к реалиям не имеет никакого отношения. Не встречал ещё ни одного компилятора, способного написать на асме лучше меня  Причём бывает что это соотношение в разы. Даже со всеми оптимизациями. Даже не очень хорошего знания ассемблера достаточно чтобы написать оптимальнее си-компилёра. Хотя я совсем не агитирую писать на чистом асм - сейчас это затея отдаёт мазохизмом. Сейчас асм только для отдельных функций. Цитата(allsettingsdone @ Jan 16 2014, 14:18)  но когда пишешь на С, то не всегда очевидно какое огромное кол-во операций может повлечь за собой та или иная простенькая строчка на С. Достаточно периодически заглядывать в листинги. И через некоторое время вам достаточно будет только бросить взгляд на эту строчку, чтобы примерно прикинуть, что получится на асме  Цитата(scifi @ Jan 16 2014, 17:05)  Настоящие мущщины кодят прямо в хексе :-)
|
|
|
|
|
Jan 16 2014, 12:16
|

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

|
Цитата(allsettingsdone @ Jan 16 2014, 12:56)  Интересно, где именно происходит сложение "$Port + GPIO_BSRR" в данном случае $Port = 0x40001800, а GPIO_BSRR = 0x10. А где бы вы сделали это сложение? Еще раз оглашу ваши условия: "оба слагаемых константы и известны до начала выполнения программы". Цитата(allsettingsdone @ Jan 16 2014, 12:56)  Для такой операции тоже ведь нужно использовать регистры Простите, но все ассемблеры такие действия выполняют в уме. Цитата(allsettingsdone @ Jan 16 2014, 12:56)  И где вообще хранится константы когда мы используем их в виде "mov R0,#4" - вот число 4 здесь, процессор же должен от куда нибудь его взять? Это описано в разделе "About the instruction descriptions" прямо в начале описания ассемблерных команд. Часто бывает полезно один раз прочитать документацию с самого начала.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 16 2014, 13:34
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
Цитата(Сергей Борщ @ Jan 16 2014, 14:16)  А где бы вы сделали это сложение? Еще раз оглашу ваши условия: "оба слагаемых константы и известны до начала выполнения программы".
Простите, но все ассемблеры такие действия выполняют в уме. Это описано в разделе "About the instruction descriptions" прямо в начале описания ассемблерных команд. Часто бывает полезно один раз прочитать документацию с самого начала. Это макрос и от пользователя может прийти что угодно (просто в этом случае я сразу прописал), вот скажем я с юарта буду посылать имя порта, в конечном итоге отправляя его в аргумент этого макроса, тогда получается что приплюсовывать "GPIO_BSRR" к имени порта (у которых код тоже задефайнен, у каждого свой) микроконтроллер будет на лету? Он же не будет знать какой порт будет следующим. Как же так?
Сообщение отредактировал allsettingsdone - Jan 16 2014, 13:36
|
|
|
|
|
Jan 16 2014, 13:55
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Так вам про это и долдонят битый час  Когда начинаешь писать программу, допустим в кеил, вы выбираете процессор под который будите писать, и прилинковываете огромный хедер с описанием регистров. Результатом является что вы пишите UART -> DR = Data; а в ассемблере берется адрес + смещение этого регистра как константа, и в нее пихается содержимое регистра отвечающего за data. Меняем процессор, меняем данные, меняем уарт, нажимаем откомпилировать код и все поехали дальше. В вашем же случаем крепко садимся на задницу, и очень четко вспоминая какие регистры есть, каких нет. И по всему тексту пошли проверять константы, смешения. Может утрированно, но смысл именно такой. Ассемблерный код чтобы он был эффективный должен быть крайне порезан. в С мы можем себе позволить Data = (int)126/24*432/12.5; но после компиляции в адрес даты будут пихать константу, и если допустим конструкция TimeInHour = Tic/CPU_FREQ * 60 * 60; - понятно то в асме будет деленный регистр в котором лежат данные Tic на константу, значение который фиг разгадаешь глядя на нее... 2.1428571428571428571428571428571e-5 а по уму должно быть не деление а умножение на 46 666.666666666666666666666666667 для клока 168 МГц. И вот как по 46 667 через год вспомнит чего вы хотели, зачем и почему это должно изменится при смене клока....  ?
|
|
|
|
|
Jan 16 2014, 17:10
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Golikov A. @ Jan 16 2014, 19:55)  в С мы можем себе позволить Data = (int)126/24*432/12.5; но после компиляции в адрес даты будут пихать константу, и если допустим конструкция TimeInHour = Tic/CPU_FREQ * 60 * 60; - понятно то в асме будет деленный регистр в котором лежат данные Tic на константу, значение который фиг разгадаешь глядя на нее... 2.1428571428571428571428571428571e-5 Вы не правы. Все современные ассемблеры точно так же умеют вычислять значения константных выражений. И даже 10 лет назад уже умели. И даже более того - средства макроязыка в ассемблерах как правило более мощные чем препроцессор си. Мне часто очень не хватает макро-возможностей асма в си, когда вспоминаю что мог позволить себе в асме... Но си скован стандартом, а ассемблер - нет. Хотя я совсем не поддерживаю ТС в его утопическом стремлении к чистому ассемблеру - жизнь его научит и отрезвит (в лице работодателя например) (если он конечно будет профессионально заниматься программированием, а не как любитель). PS: Кстати - совсем не согласен с тем кто тут писал что ассемблер ARM - сложный. Из всех асмов что я когда-либо изучал, этот - самый простой. Достаточно хотя-бы взглянуть на асм TI DSP 5000-ного семейства.
|
|
|
|
|
Jan 16 2014, 18:57
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Golikov A. @ Jan 17 2014, 00:00)  помню там было много приколов с тем что branch делался 3 такта, и часто эти 3 такта шли на доп вычисления, типа 1 такт бранч, а потом еще 2 команды которые выполнялись до бранча. Или когда ффт на 2 алу раскидывалось в параллель. Примерно тогда я зарекся соревноваться в компилятором. На TI C55xx если мне не изменяет память 6-тактный конвеер и переходы (не внутри RPT) 4-5-6 тактов. Там я применял много способов оптимизации в том числе и конвееризацию вычислений внутри циклов, когда одновременно выполнялась голова цепочки команд обработки сэмпла в одном АЛУ в то время как в те же самые такты выполнялся хвост этой цепочки команд для предыдущего сэмпла в другом АЛУ. Что уж говорить про параллельные чтения/сохранения в ОЗУ. И зря зареклись. Никогда ещё ни до ни после я по эффективности кода так не превосходил си-компилятор как тогда - мой код на асм получался в РАЗЫ меньше и быстрее. Оптимизировав инструкции по размеру, спарив их, убрав все штрафы (stall-ы), раскидав выполнение по разным шагам конвеера, загнав цикл в RPTBLOCAL, использовав разные фичи типа циклической адресации и т.п. можно было в разы уделать компилятор А вот на ARM выигрыш от такой оптимизации будет значительно меньше и смысл в ней значительно меньше. Изредка, когда приходится что-то написать на асм для ARM/Cortex-M с оптимизацией времени выполнения, с тоской вспоминаю C55xx....
|
|
|
|
|
Jan 17 2014, 07:13
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
вам видать плохой компилятор достался  ну или у вас ооочень большая голова. я разглядывая полученные коды находя крайне странно-нелогичные конструкции длительное время втыкая в них понимал что они настолько хитро упакованы, что я бы даже не поглядел бы в эту сторону. Хотя может если набраться опыта то за пару лет сам начнешь так мыслить... но где теперь этот проц и тот код? Стоил бы он нескольких лет упорных втыканий в АСМ? Все течет все меняется... Цитата(_Pasha @ Jan 16 2014, 23:01)  побивающее компиляторы как по скорости так и по размеру. а это не нарушает закон сохранения энергии?
|
|
|
|
|
Jan 17 2014, 10:11
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
не я про другое.
иногда интерпритатор работает медленнее, но код становиться меньше иногда он работает быстрее, но требует больших команд и код становится больше иногда он работает и медленнее и код больше
но вот чтобы был интерпритатор который и быстрее и код меньше, я себе слабо это представляю, ибо нарушает закон сохранения энергии, принцип неопределенности Гейзенберга ну и так далее.... Если у вас есть объяснения как такое получает мне правда интересно, без иронии...
П.С. Я как представитель общества считаю что когда кто-то как ТС начинает изучать ассемблер, то он очевидно заблуждается, и заблуждение настолько очевидно, что нет никаких сил не попытаться его спасти%)... Подозреваю что всеми движет примерно похожее чувство.
|
|
|
|
|
Jan 17 2014, 10:24
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(_Pasha @ Jan 17 2014, 12:09)  Подозрительным образом сообщество мгновенно накидывается на человека Да никто не накидывается. Правда состоит в том, что большинство отвечающих как раз серьёзно посидели на ASM. Более того, в образовательных целях, очень даже правильно позаниматься ASMом для ясного представления, как работает процессор. Хорошо бы посидеть на нескольких. Очень полезно попробовать соптимизировать какую-нибудь функцию Си. Я, например, даже при вылизывании, сначала всё пишу на Си, убеждаюсь в работоспособности и только потом переписываю узкие места. Убеждаясь, что всё продолжает работать. Просто жалко тех начинающих, кто пытается протянуть какую-нибудь философию либо религию в техническую область. Ещё недавно генеральный директор Мерседеса говорил, что скорее закроет свои заводы чем выпустит машину с передним приводом. ))
|
|
|
|
|
Jan 17 2014, 17:00
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Golikov A. @ Jan 17 2014, 14:11)  иногда интерпритатор работает медленнее, но код становиться меньше иногда он работает быстрее, но требует больших команд и код становится больше иногда он работает и медленнее и код больше
но вот чтобы был интерпритатор который и быстрее и код меньше, я себе слабо это представляю, ибо нарушает закон сохранения энергии, принцип неопределенности Гейзенберга ну и так далее.... Если у вас есть объяснения как такое получает мне правда интересно, без иронии... Надо какое-то пространство обсуждения принять. Потому что, скажем, в случае JIT-компиляции, - это нарушение закона сохранения или расширение множества свойств наблюдаемой системы? А то мы так быстро заблудимся
|
|
|
|
|
Jan 17 2014, 17:25
|
Гуру
     
Группа: Участник
Сообщений: 2 219
Регистрация: 16-08-12
Из: Киров
Пользователь №: 73 143

|
Цитата(jcxz @ Jan 16 2014, 21:10)  Хотя я совсем не поддерживаю ТС в его утопическом стремлении к чистому ассемблеру - жизнь его научит и отрезвит (в лице работодателя например) (если он конечно будет профессионально заниматься программированием, а не как любитель). Если ТС уж так хочет сравнить си и асм, то пусть попробует написать поддержку файловой системы через УСБ флешку  И потом еще попробует перенести все это счастье на другой проц... А мы посмотрим, сколь лет ему на это понадобится ЗЫ. Мы все стремимся, используя более высокоуровневые языки, облегчить себе жизнь, потому что у заказчиков требования тоже растут неплохо. Если 5-10 лет назад им было достаточно настройки устройства через простейшую менюшку с кнопками вниз\вверх, то теперь подавай удаленный доступ, желательно через инет, обновление прошивки по 1 тычку кнопки и т.д. Идите в ногу со временем, а не занимайтесь глупостями в виде чистого асма!
|
|
|
|
|
Jan 17 2014, 18:27
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(mantech @ Jan 17 2014, 21:25)  ЗЫ. Мы все стремимся, испольуя более высокоуровневые языки, облегчить себе жизнь, потому что у заказчиков требования тоже растут неплохо. Если 5-10 лет назад им было достаточно настройки устройства через простейшую менюшку с кнопками вниз\вверх, то теперь подавай удаленный доступ, желательно через инет, обновление прошивки по 1 тычку кнопки и т.д. Идите в ногу со временем, а не занимайтесь глупостями в виде чистого асма! С такими запросами и Си - совсем не панацея. Там уже это называется "экосистема", наверное. В любом случае, асм совсем не в тему, конечно.
|
|
|
|
|
Jan 17 2014, 20:47
|
Знающий
   
Группа: Свой
Сообщений: 549
Регистрация: 13-07-10
Из: Солнечногорск-7
Пользователь №: 58 414

|
Цитата(Сергей Борщ @ Jan 16 2014, 11:40)  Разворачиваем, получаем Код mov32 R0,#(GPIOC + GPIO_BSRR) mov32 R1,#PIN9 str R1,[R0] mov32 R0,#(GPIOC + GPIO_BSRR) mov32 R1,#PIN8 str R1,[R0] Дважды грузится R0 одинаковым значением. И где хваленый выигрыш от Ассемблера? Такого даже самый плохой Си-компилятор себе не позволяет. Не морочьте себе и нам голову, лучше потратьте это время и эти усилия на более глубокое изучение Си или Си с плюсами. Поверьте, это будет гораздо продуктивнее и полезнее. Ассемблер на уровне, достатотчном для анализа листингов и пошаговой отладки вы уже знаете Постоянная бесполезная перезагрузка регистров одними и теми же значениями -- любимое занятие GCC. Вообще, высокая эффективность компиляторов -- это сказки. Даже лучшие из них дают не такой уж хороший код. Другое дело, что далеко не всегда имеет смысл писать вручную на ассемблере -- обычно производительность и компактность не являются главными критериями, хотя иногда они и важны. В общем, надо подходить к этому без фанатизма. Сравнительная скорость разработки программы на ассемблере и языке высокого уровня очень сильно зависит от задачи и от системы команд. Если там сплошные опросы, манипуляции с битами и переходы по условиям, разница весьма невелика. А вот если сложные расчёты -- очень заметная (то, что на ЯВУ пишется за 5-10 мин, на ассемблере можно и час, и два делать). Скорость отладки больше зависит от используемого языка; с числом строк программы она на самом деле связана лишь в том случае, если сравниваются программы на одном и том же языке. Между Си и ассемблером по числу ошибок особой разницы нет: и там, и там крайне легко допустить какие-нибудь ляпы, но на Си их искать часто бывает сложней (там куда более заковыристые проблемы могут быть по сравнению с ассемблером, где, пожалуй, основной источник ошибок -- неверный номер регистра). Вот если сравнивать ассемблер и Си с Адой или хотя бы Паскалем -- разница в числе ошибок будет в разы. Цитата(Golikov A. @ Jan 16 2014, 22:00)  Но моя убежденность в том что сишный код с одной платформы на другую еще можно перенести, а асмовый - практически всегда беда... Что значит с платформы на платформу? Если речь о разных архитектурах процессоров (скажем, с IA-32 на ARM или наоборот), то код на любом языке высокого уровня можно перенести, если есть компилятор, ну а на ассемблере нельзя -- ведь он прямо отражает архитектуру машины. Но если говорить о процессорах одной архитектуры, тогда проблем нет. Скажем, если надо перенести программу с какого-нибудь STM32 на какой-нибудь NXPшный микроконтроллер (и тот, и другой принадлежат к архитектуре ARM), то что на ассемблере, что на Си придётся переписывать код, относящийся к инициализации синхронизации, работе с периферией и т.д. -- поскольку эти вещи у разных МК различаются. Однако код, собственно решающий задачу, остаётся неизменным. Конечно, это при условии, если он написан достаточно грамотно -- но то же самое относится и к коду на ЯВУ (если ты в каждой функции напихал код, зависящий от конкретной модели МК, то и переделывать каждую функцию придётся).
|
|
|
|
|
Jan 17 2014, 21:09
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(SII @ Jan 18 2014, 00:47)  Между Си и ассемблером по числу ошибок особой разницы нет: и там, и там крайне легко допустить какие-нибудь ляпы, но на Си их искать часто бывает сложней (там куда более заковыристые проблемы могут быть по сравнению с ассемблером Сегодня такие грабли выловил....ужас. В общем, додумался я описать структуру в теле функции. Переменная локальная, какая разница вроде бы... оказалось что в elf при этом что-то приписывается такое, что не все его потом понимают. Нужен был протеус, а он не грузил файл... только описание структуры вынес - заработало. Цитата код на любом языке высокого уровня можно перенести, если есть компилятор, ну а на ассемблере нельзя Псевдокод - можно! Если макросредства не меняются.
|
|
|
|
|
Jan 18 2014, 06:27
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
напишите виндус ан ассемблере, а потом рассказывайте что С код труднее отлаживать...
описали структуру не так... так в ассемблере структуры вообще нет. А реюзинг? А Класс с++?
С++ дает огромные преимущества в повторном использовании кода, правда конечно если вы не балуетесь перегрузкой сложения вычитанием, а вычитания сложением.
С, С++, ява, асемблер - это инструменты. Новые не появлялись бы если прошлые всех устраивали, но так же старые не оставались в строю, если бы новые делали все что надо. Правда как всегда по середине, но смещена в сторону частоты использования.
|
|
|
|
|
Jan 18 2014, 06:37
|
Знающий
   
Группа: Свой
Сообщений: 549
Регистрация: 13-07-10
Из: Солнечногорск-7
Пользователь №: 58 414

|
Цитата(_Pasha @ Jan 18 2014, 01:09)  Псевдокод - можно! Если макросредства не меняются. Псевдокод будет уступать по эффективности родному ассемблеру конкретной архитектуры, поскольку, используя этот самый родной ассемблер, можно эффективно использовать особенности данной архитектуры, а псевдокод (если я правильно понял, что Вы имеете в виду) будет сродни языку высокого уровня -- представлять некие машинно-независимые абстракции, которые нужно транслировать в машинный код. Скажем, такая операция, как пересылка или сравнение последовательности байтов в двух областях памяти, на одной архитектуре потребует целой подпрограммы, на другой -- 2-3 инструкций, на третьей -- вообще одной инструкции, но при этом будут различаться требования к размещению адресов областей и т.д. Сделать эффективную трансляцию подобного с помощью макросов под любые архитектуры не получится -- всегда будут всплывать особенности и ограничения конкретных архитектур (скажем, на IA-32 эта задача формально решается одной инструкцией с префиксом повторения, однако исходные данные должны быть загружены в строго определённые регистры; на ARM требуется несколько команд, но зато можно пользоваться любыми регистрами, в Системе 360 и её потомках, включая современные мэйнфреймы, есть две инструкции для решения каждой из этих задач с разным способом указания областей памяти, и в разных случаях надо использовать одну из них, на VAX это решается одной инструкцией без каких-то особых ограничений и т.д.). Ну а поскольку одна из основных причин использования ассемблера заключается в получении большей эффективности, чем при кодировании той же задачи на каком-то ЯВУ, жертвовать ею ради такой "макропереносимости" смысла нет. А вот в рамках одной архитектуры макросы очень сильно могут помочь. У меня, например, есть набор своих макросов, которые помогают эффективнее использовать язык ассемблера в зависимости от того, какой набор команд -- Thumb или Thumb-2 -- доступен, а также что из себя представляют операнды. Т.е. программа пишется частью обычными инструкциями (там, где разницы нет), частью такими макросами, а они внутри себя используют условную трансляцию, чтобы сформировать наиболее подходящую последовательность инструкций. Например, мой макрос MOVC загружает в регистр константу, при этом он может превратиться в инструкцию movs, movw или ldr в зависимости от значения константы и доступной системы команд. Ну а в тех случаях, когда макросы помочь не могут (из-за того, что задача уж очень специализированная), но нужно обеспечить переносимость под разные версии архитектуры, я уже сам явным образом использую условную трансляцию.
|
|
|
|
|
Jan 18 2014, 08:04
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(SII @ Jan 18 2014, 10:37)  Псевдокод будет уступать по эффективности родному ассемблеру конкретной архитектуры, поскольку, используя этот самый родной ассемблер, можно эффективно использовать особенности данной архитектуры, а псевдокод (если я правильно понял, что Вы имеете в виду) будет сродни языку высокого уровня -- представлять некие машинно-независимые абстракции, которые нужно транслировать в машинный код. Ну например... Сделали конструкцию, которая является нечто похожим на Код typedef void (*process_t)(void); const process_t flowchart[]={&proc1,&proc2,&proc3};
void steps(uint num) { flowchart[num](); } Причем, зная что мы делаем таблицу указателей на функции не больше 256 элементов, иначе крыша счастливого программера вспухнет  можем ввести псевдокод например 16-битный <0xFF><адрес-в-таблице-функций> как безусловное исполнение, ну там... несколько вариантов условных, объяснить кто куда данные поставляет. Это все в пределах 16 бит можно. и цикл, который такую таблицу схавает, уже описать в виде макроса Заметьте, ничего святого  никак микро-интерпретатор не претендует на роль глобальной системы. просто вкрапления. Не нравится такая система? Тут же конструируем и применяем другую. Регистров в контроллере многовато? ок, можно параллелить процессы с меньшим числом регистров. портирование сводится ессно к реализации зоопарка таких штук.
|
|
|
|
|
Jun 8 2014, 03:38
|

Участник

Группа: Участник
Сообщений: 44
Регистрация: 26-01-10
Из: Санкт-Петербург
Пользователь №: 55 080

|
Добрый день Что-бы не плодить темы. Помогите стартануть проект на asm в iar. CODE NAME test PUBLIC __iar_program_start SECTION .intvec : CODE (2) CODE #include "startup_stm32f072.s" SECTION .intvec : CODE (2) CODE SECTION .text : CODE (2) CODE __iar_program_start B init ;main init: main NOP B main END
Этот простейший проект не компилится, выдаются ошибки: Warning[25]: Label 'Reset_Handler' is defined pubweak in a section implicitly declared root E:\IAR_ARM\startup_stm32f072.s 121 Warning[18]: END of program while in include file E:\IAR_ARM\startup_stm32f072.s 345 Error[50]: Undefined symbol:'__iar_program_start' E:\IAR_ARM\startup_stm32f072.s 124 Может кто-нибудь помочь примером любого многофайлового asm-овского проекта для IAR для STM32? (интересует собственено начальная часть , где подключаются процедуры из других файлов, декларируются переменные, вектора прерываний и т.д.) И еще - как задать расположение переменных в RAM, констант в eeprom и flash? Заранее спасибо
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|