Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 Ассемблер. Идеи и приёмы написания
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
allsettingsdone
По ассемблеру для арм документации и разного рода примеров гораздо меньше для С. Начал осваивать и возникли сомнения, правильный ли подход частого использования макросов и где та грань, свыше которой не стоит заморачиваться с написанием кода. В ассемблера я не силён, в основном по-любительски пишу на С. Но вот раз начал осваивать асм, сделал несколько элементарных макросов для битовых операций, настройки и использования портов. Вопрос в том правильно ли это делать и использовать таким образом (когда в коде используются много макросов), или может быть есть более рациональный способ, как лучше писать на асме для арм. Вот примерчик:
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 прикреплен:
Golikov A.
Все зависит от того чего вы хотите в итоге.

Если вы упражняетесь смысл имеет. Если это коммерческий продукт убежден что не имеет.

С темпами развития процессоров сейчас на первый план выход не отдельная производительность одной функции, а удобство поддержки, модификации и расширения программного решения. В том числе и перенос его на другие процессоры и платформы. А для этого чем более абстрактно написан код и чем более читаемо и понятно он написан тем лучше.

код из раздела
Код
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? То есть просто по ходу программы написанной на С этот макрос вызывать нельзя. А если вы будете следить за этими регистрами всю программу, то это как раз ярчайший пример АБСОЛЮТНО не поддерживаемого кода. Любое шевеление в будущем чревато багами.
allsettingsdone
Встраивать асемблеровский код в проект на С я не планирую, идея в написании всего проекта на асм, так что я условился приблизительно регистры R0-R3 использовать с оглядкой на то что они будут постоянно меняться, так как задействованы почти во всех макросах. А уже по ходу выполнения программы буду держать в поле зрения другие регистры с ключевой информацией.
Вот ещё что интересно: одно и то же действие можно сделать разными командами и бывает не понятно как лучше поступить. Вот например загрузка в регистр адреса из памяти: (кусочек кода из макроса)
Код
mov32        R0,#$Port

или
Код
ldr          R0,=$Port

В итоге эти две строчки равнозначны и вот какую из них лучше применять совсем непонятно.

Хотелось бы узнать как бы идею и философию подхода к программированию на ассемблере для мк. (может есть годные примеры такого?)

Встраивать асемблеровский код в проект на С я не планирую, идея в написании всего проекта на асм, так что я условился приблизительно регистры R0-R3 использовать с оглядкой на то что они будут постоянно меняться, так как задействованы почти во всех макросах. А уже по ходу выполнения программы буду держать в поле зрения другие регистры с ключевой информацией.
Вот ещё что интересно: одно и то же действие можно сделать разными командами и бывает не понятно как лучше поступить. Вот например загрузка в регистр адреса памяти: (кусочек кода из макроса)
Код
mov32        R0,#$Port

или
Код
ldr          R0,=$Port

В итоге эти две строчки равнозначны и вот какую из них лучше применять совсем непонятно.

Или вот ещё
Код
mov32            R0,#($Port + GPIO_BSRR)

Тоже интересно где именно происходит это сложение? Как я понимаю в на эту строчку уйдет далеко не два такта микроконтроллера?

Хотелось бы узнать как бы идею и философию подхода к программированию на ассемблере для мк. (может есть годные примеры такого?)

PS: с BFI разобрался
scifi
Цитата(allsettingsdone @ Jan 16 2014, 09:38) *
Встраивать асемблеровский код в проект на С я не планирую, идея в написании всего проекта на асм

Ну и зря. Это просто борьба с ветряными мельницами какая-то. Она имеет право на жизнь, конечно, но лучше потратьте своё время на что-нибудь более полезное и интересное.
Golikov A.
Поддерживаю.
Весь проект на ассемблере - это долго, опасно, и не эффективно, если конечно вы делаете не новогоднюю гирлянду с 2 режимами мигания.

Убейте книгой того кто вам сказал что крутые железячники все пишут на ассемблере, это было верно для готов 80. Сейчас уже давно и С++ практикуют, потому что стоимость машинного такта неуклонно падает. А требования к скорости и качеству разработки очень быстро растут.

Поглядите новым продуктам ставят сроки жизни и актуальности 4-5 лет. И если вы на ассемблере год будите писать программу, и год ее отлаживать, то через 2-3 оставшихся года при переходе на новый проц, вы что опять 2 года жизни прибора отъедите? Кому нужна такая разработка?

Максимум где допустим ассемблер - это вставки в особо критических местах кода, да и то в 95% случаев оптимизаторы современных языков делают эту работу лучше.

Не ходите валить лес с топором как делали наши деды, уже давно есть бензопилы!
Сергей Борщ
Цитата(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 одинаковым значением. И где хваленый выигрыш от Ассемблера? Такого даже самый плохой Си-компилятор себе не позволяет. Не морочьте себе и нам голову, лучше потратьте это время и эти усилия на более глубокое изучение Си или Си с плюсами. Поверьте, это будет гораздо продуктивнее и полезнее. Ассемблер на уровне, достатотчном для анализа листингов и пошаговой отладки вы уже знаете.
Ozelot
Топикстартер задал конкретный вопрос в надежде получить от господ ПРОФЕССИОНАЛОВ конкретный ответ и если вы не можете его дать, то наверно лучше помолчать (наболело).
Я для 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, я думаю если поискать, то можно много информации найти.
Желаю удачи sm.gif
allsettingsdone
Как раз читаю одну из этих книг. Что касается С, то на нем я как раз и пишу, но есть мнение что качественно и без извращений, писать на асм может дать выигрыш в прозрачности кода и более логически правильному её написанию и именно к микроконтроллерам это очень даже применимо.
Я думаю что современный компилятор таки может гораздо лучше человека составить асм код, но когда пишешь на С, то не всегда очевидно какое огромное кол-во операций может повлечь за собой та или иная простенькая строчка на С.
scifi
Цитата(allsettingsdone @ Jan 16 2014, 12:18) *
Я думаю что современный компилятор таки может гораздо лучше человека составить асм код, но когда пишешь на С, то не всегда очевидно какое огромное кол-во операций может повлечь за собой та или иная простенькая строчка на С.

На самом деле всё-таки почти всегда очевидно, что он там нагенерит. А если не очевидно, то заглянуть в дизассемблер совсем не сложно.
Ну и погоня за тактами - это ложная и вредная цель. Реально такая задача возникает крайне редко, и решается она небольшой ассемблерной вставкой.
MALLOY2
Цитата
но когда пишешь на С, то не всегда очевидно какое огромное кол-во операций может повлечь за собой та или иная простенькая строчка на С.


Вы всегда можете открыть листинги и посмотреть что сделал компилятор и подправить.
Golikov A.
ассемблер очевиднее С, только для ОЧЕНЬ маленьких программок из раздела мигаем лампочкой. Да и то С тут очевиднее...
allsettingsdone
Ладно, а что по поводу таких вещей:
Код
mov32            R0,#($Port + GPIO_BSRR)

Интересно, где именно происходит сложение "$Port + GPIO_BSRR" в данном случае $Port = 0x40001800, а GPIO_BSRR = 0x10. Для такой операции тоже ведь нужно использовать регистры, я пытался проследить этот момент, но именного таких чисел не увидел. И где вообще хранится константы когда мы используем их в виде "mov R0,#4" - вот число 4 здесь, процессор же должен от куда нибудь его взять? Откуда именно (если из ПЗУ, то как узнать по какому адресу компилятор что,где ложит)?

Цитата(Golikov A. @ Jan 16 2014, 12:23) *
ассемблер очевиднее С, только для ОЧЕНЬ маленьких программок из раздела мигаем лампочкой. Да и то С тут очевиднее...

Любую программу же можно разбить на отдельные блоки/функции/файлы отвечающие за что-то одно. И можно будет во всем разобраться.
scifi
Цитата(allsettingsdone @ Jan 16 2014, 14:56) *
Любую программу же можно разбить на отдельные блоки/функции/файлы отвечающие за что-то одно. И можно будет во всем разобраться.

Настоящие мущщины кодят прямо в хексе :-)
jcxz
Цитата(allsettingsdone @ Jan 16 2014, 14:18) *
Как раз читаю одну из этих книг. Что касается С, то на нем я как раз и пишу, но есть мнение что качественно и без извращений, писать на асм может дать выигрыш в прозрачности кода и более логически правильному её написанию и именно к микроконтроллерам это очень даже применимо.

Как правило, наоборот - чем код объёмнее - тем он менее прозрачен, а на асме код всяко будет ОБЪЁМНЕЕ sm.gif

Цитата(allsettingsdone @ Jan 16 2014, 14:18) *
Я думаю что современный компилятор таки может гораздо лучше человека составить асм код,

Что-то очень часто приходится слышать это заблуждение.... По-моему пошло из рекламных буклетов си-компиляторов и к реалиям не имеет никакого отношения.
Не встречал ещё ни одного компилятора, способного написать на асме лучше меня sm.gif
Причём бывает что это соотношение в разы. Даже со всеми оптимизациями.
Даже не очень хорошего знания ассемблера достаточно чтобы написать оптимальнее си-компилёра.
Хотя я совсем не агитирую писать на чистом асм - сейчас это затея отдаёт мазохизмом. Сейчас асм только для отдельных функций.

Цитата(allsettingsdone @ Jan 16 2014, 14:18) *
но когда пишешь на С, то не всегда очевидно какое огромное кол-во операций может повлечь за собой та или иная простенькая строчка на С.

Достаточно периодически заглядывать в листинги. И через некоторое время вам достаточно будет только бросить взгляд на эту строчку, чтобы примерно прикинуть, что получится на асме sm.gif

Цитата(scifi @ Jan 16 2014, 17:05) *
Настоящие мущщины кодят прямо в хексе :-)

biggrin.gif
SasaVitebsk
1. Для некоторых процессоров ассемблер достаточно простой и наглядный. ARM ассемблер этими свойствами очевидно не обладает. Это мнение разработчиков компиляторов, ссылаясь на слова Тревора.
2. Написать несложную программу на простом ассемблере, с использованием макросов действительно несложно. Но Вам сказали об переносимости и поддерживаемости (сопровождении). А здесь ассемблер даже не мина а огромная бомба.
Для того, чтобы Вы сами приняли правильное решение предлагаю Вам несложный эксперимент. Напишите проект на ASM. Сделайте выдержку 1-2 месяца. Внесите в него изменения. Только изменения не сразу продумайте, а попросите кого-нибудь со стороны, чтобы он придумал Вам изменения. Ну и отладьте.
Я думаю, больше у Вас вопросов к форуму не будет.
PS: Я писал значительные проекты на ASM.
Сергей Борщ
Цитата(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" прямо в начале описания ассемблерных команд. Часто бывает полезно один раз прочитать документацию с самого начала.
allsettingsdone
Цитата(Сергей Борщ @ Jan 16 2014, 14:16) *
А где бы вы сделали это сложение? Еще раз оглашу ваши условия: "оба слагаемых константы и известны до начала выполнения программы".

Простите, но все ассемблеры такие действия выполняют в уме.
Это описано в разделе "About the instruction descriptions" прямо в начале описания ассемблерных команд. Часто бывает полезно один раз прочитать документацию с самого начала.

Это макрос и от пользователя может прийти что угодно (просто в этом случае я сразу прописал), вот скажем я с юарта буду посылать имя порта, в конечном итоге отправляя его в аргумент этого макроса, тогда получается что приплюсовывать "GPIO_BSRR" к имени порта (у которых код тоже задефайнен, у каждого свой) микроконтроллер будет на лету? Он же не будет знать какой порт будет следующим. Как же так?
Golikov A.
Так вам про это и долдонят битый часsm.gif

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

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 через год вспомнит чего вы хотели, зачем и почему это должно изменится при смене клока.... sm.gif?



Сергей Борщ
Цитата(allsettingsdone @ Jan 16 2014, 15:34) *
тогда получается что приплюсовывать "GPIO_BSRR" к имени порта (у которых код тоже задефайнен, у каждого свой) микроконтроллер будет на лету?
Нет, не получится. Если вы почитаете описание команды mov то увидите, что вторым операндом должна быть константа. Хотите вычислять на лету - надо будет писать кусок кода из нескольких команд. Чтобы убедиться - напишите желаемое на Си, скомпилите и посмотрите листинг. При желании можете взять его за основу и попытаться соптимизировать.
jcxz
Цитата(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 лет назад уже умели.
И даже более того - средства макроязыка в ассемблерах как правило более мощные чем препроцессор си.
Мне часто очень не хватает макро-возможностей асма в си, когда вспоминаю что мог позволить себе в асме... crying.gif
Но си скован стандартом, а ассемблер - нет.
Хотя я совсем не поддерживаю ТС в его утопическом стремлении к чистому ассемблеру - жизнь его научит и отрезвит (в лице работодателя например) twak.gif
(если он конечно будет профессионально заниматься программированием, а не как любитель).

PS: Кстати - совсем не согласен с тем кто тут писал что ассемблер ARM - сложный. Из всех асмов что я когда-либо изучал, этот - самый простой.
Достаточно хотя-бы взглянуть на асм TI DSP 5000-ного семейства. rolleyes.gif
Golikov A.
ага или на асм ДСПешника со сдвоенным АЛУ,

помню там было много приколов с тем что branch делался 3 такта, и часто эти 3 такта шли на доп вычисления, типа 1 такт бранч, а потом еще 2 команды которые выполнялись до бранча. Или когда ффт на 2 алу раскидывалось в параллель. Примерно тогда я зарекся соревноваться в компилятором.

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

А не прав, так не прав, это как бы пример может и не корректный. Но моя убежденность в том что сишный код с одной платформы на другую еще можно перенести, а асмовый - практически всегда беда...
jcxz
Цитата(Golikov A. @ Jan 17 2014, 00:00) *
помню там было много приколов с тем что branch делался 3 такта, и часто эти 3 такта шли на доп вычисления, типа 1 такт бранч, а потом еще 2 команды которые выполнялись до бранча. Или когда ффт на 2 алу раскидывалось в параллель. Примерно тогда я зарекся соревноваться в компилятором.

На TI C55xx если мне не изменяет память 6-тактный конвеер и переходы (не внутри RPT) 4-5-6 тактов.
Там я применял много способов оптимизации в том числе и конвееризацию вычислений внутри циклов, когда одновременно выполнялась голова цепочки команд обработки сэмпла в одном АЛУ в то время как
в те же самые такты выполнялся хвост этой цепочки команд для предыдущего сэмпла в другом АЛУ.
Что уж говорить про параллельные чтения/сохранения в ОЗУ.
И зря зареклись. Никогда ещё ни до ни после я по эффективности кода так не превосходил си-компилятор как тогда - мой код на асм получался в РАЗЫ меньше и быстрее. rolleyes.gif
Оптимизировав инструкции по размеру, спарив их, убрав все штрафы (stall-ы), раскидав выполнение по разным шагам конвеера, загнав цикл в RPTBLOCAL, использовав разные фичи типа циклической адресации и т.п. можно было в разы уделать компилятор biggrin.gif
А вот на ARM выигрыш от такой оптимизации будет значительно меньше и смысл в ней значительно меньше.
Изредка, когда приходится что-то написать на асм для ARM/Cortex-M с оптимизацией времени выполнения, с тоской вспоминаю C55xx....
_Pasha
Я бы если бы так упорно писал бы на ассемблере(бы),
то занялся (бы) псевдомашиной, всякими командами и таблицами, тогда на выходе получилось(бы) нечто, побивающее компиляторы как по скорости так и по размеру. И если со вторым как бы не проблема, то с первым еще надо много думать.
Если Вы не пишете на Си, Вы придете к интерпретаторам.
Golikov A.
вам видать плохой компилятор досталсяsm.gif ну или у вас ооочень большая голова.

я разглядывая полученные коды находя крайне странно-нелогичные конструкции длительное время втыкая в них понимал что они настолько хитро упакованы, что я бы даже не поглядел бы в эту сторону. Хотя может если набраться опыта то за пару лет сам начнешь так мыслить... но где теперь этот проц и тот код? Стоил бы он нескольких лет упорных втыканий в АСМ? Все течет все меняется...

Цитата(_Pasha @ Jan 16 2014, 23:01) *
побивающее компиляторы как по скорости так и по размеру.


а это не нарушает закон сохранения энергии?



_Pasha
Цитата(Golikov A. @ Jan 17 2014, 11:13) *
а это не нарушает закон сохранения энергии?

Подозрительным образом сообщество мгновенно накидывается на человека, который только намекнул на то, что хочет заниматься асмом. biggrin.gif
И это довольно давно продолжается. В данном случае закон сохранения энергии нарушается действительно, поскольку например мне лично все равно, развивается компиляторостроение Си или нет и дивидендов от этого процесса как будучи агентом влияния я не получу никаких.
Golikov A.
не я про другое.

иногда интерпритатор работает медленнее, но код становиться меньше
иногда он работает быстрее, но требует больших команд и код становится больше
иногда он работает и медленнее и код больше

но вот чтобы был интерпритатор который и быстрее и код меньше, я себе слабо это представляю, ибо нарушает закон сохранения энергии, принцип неопределенности Гейзенберга ну и так далее.... Если у вас есть объяснения как такое получает мне правда интересно, без иронии...


П.С. Я как представитель общества считаю что когда кто-то как ТС начинает изучать ассемблер, то он очевидно заблуждается, и заблуждение настолько очевидно, что нет никаких сил не попытаться его спасти%)... Подозреваю что всеми движет примерно похожее чувство.



SasaVitebsk
Цитата(_Pasha @ Jan 17 2014, 12:09) *
Подозрительным образом сообщество мгновенно накидывается на человека

Да никто не накидывается. rolleyes.gif
Правда состоит в том, что большинство отвечающих как раз серьёзно посидели на ASM. Более того, в образовательных целях, очень даже правильно позаниматься ASMом для ясного представления, как работает процессор. Хорошо бы посидеть на нескольких. Очень полезно попробовать соптимизировать какую-нибудь функцию Си.

Я, например, даже при вылизывании, сначала всё пишу на Си, убеждаюсь в работоспособности и только потом переписываю узкие места. Убеждаясь, что всё продолжает работать.

Просто жалко тех начинающих, кто пытается протянуть какую-нибудь философию либо религию в техническую область. Ещё недавно генеральный директор Мерседеса говорил, что скорее закроет свои заводы чем выпустит машину с передним приводом. ))
Сергей Борщ
Цитата(_Pasha @ Jan 17 2014, 10:09) *
Подозрительным образом сообщество мгновенно накидывается на человека, который только намекнул на то, что хочет заниматься асмом.
Если человек решит спрыгнуть с людного пешеходного моста - наверное, тоже найдется какое-то количество желающих его отговорить. Ситуация, на мой взгляд, схожая - человек собирается впустую потратить часть жизни.
_Pasha
Цитата(Golikov A. @ Jan 17 2014, 14:11) *
иногда интерпритатор работает медленнее, но код становиться меньше
иногда он работает быстрее, но требует больших команд и код становится больше
иногда он работает и медленнее и код больше

но вот чтобы был интерпритатор который и быстрее и код меньше, я себе слабо это представляю, ибо нарушает закон сохранения энергии, принцип неопределенности Гейзенберга ну и так далее....
Если у вас есть объяснения как такое получает мне правда интересно, без иронии...


Надо какое-то пространство обсуждения принять. Потому что, скажем, в случае JIT-компиляции, - это нарушение закона сохранения или расширение множества свойств наблюдаемой системы? А то мы так быстро заблудимся sm.gif
mantech
Цитата(jcxz @ Jan 16 2014, 21:10) *
Хотя я совсем не поддерживаю ТС в его утопическом стремлении к чистому ассемблеру - жизнь его научит и отрезвит (в лице работодателя например)
(если он конечно будет профессионально заниматься программированием, а не как любитель).


Если ТС уж так хочет сравнить си и асм, то пусть попробует написать поддержку файловой системы через УСБ флешку biggrin.gif И потом еще попробует перенести все это счастье на другой проц... А мы посмотрим, сколь лет ему на это понадобится wacko.gif

ЗЫ. Мы все стремимся, используя более высокоуровневые языки, облегчить себе жизнь, потому что у заказчиков требования тоже растут неплохо. Если 5-10 лет назад им было достаточно настройки устройства через простейшую менюшку с кнопками вниз\вверх, то теперь подавай удаленный доступ, желательно через инет, обновление прошивки по 1 тычку кнопки и т.д. Идите в ногу со временем, а не занимайтесь глупостями в виде чистого асма!
scifi
Цитата(mantech @ Jan 17 2014, 21:25) *
ЗЫ. Мы все стремимся, испольуя более высокоуровневые языки, облегчить себе жизнь, потому что у заказчиков требования тоже растут неплохо. Если 5-10 лет назад им было достаточно настройки устройства через простейшую менюшку с кнопками вниз\вверх, то теперь подавай удаленный доступ, желательно через инет, обновление прошивки по 1 тычку кнопки и т.д. Идите в ногу со временем, а не занимайтесь глупостями в виде чистого асма!

С такими запросами и Си - совсем не панацея. Там уже это называется "экосистема", наверное. В любом случае, асм совсем не в тему, конечно.
Golikov A.
Цитата(_Pasha @ Jan 17 2014, 21:00) *
Надо какое-то пространство обсуждения принять. Потому что, скажем, в случае JIT-компиляции, - это нарушение закона сохранения или расширение множества свойств наблюдаемой системы? А то мы так быстро заблудимся sm.gif


я не знаю... но и жит компиляция может давать выигрышь за счет более полной поддержки свойств процессора. Но может, а не дает... да и свойства не так часто появляются... ну вообщем наверное это все не для этой темы...
SII
Цитата(Сергей Борщ @ 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), то что на ассемблере, что на Си придётся переписывать код, относящийся к инициализации синхронизации, работе с периферией и т.д. -- поскольку эти вещи у разных МК различаются. Однако код, собственно решающий задачу, остаётся неизменным. Конечно, это при условии, если он написан достаточно грамотно -- но то же самое относится и к коду на ЯВУ (если ты в каждой функции напихал код, зависящий от конкретной модели МК, то и переделывать каждую функцию придётся).
_Pasha
Цитата(SII @ Jan 18 2014, 00:47) *
Между Си и ассемблером по числу ошибок особой разницы нет: и там, и там крайне легко допустить какие-нибудь ляпы, но на Си их искать часто бывает сложней (там куда более заковыристые проблемы могут быть по сравнению с ассемблером


Сегодня такие грабли выловил....ужас. В общем, додумался я описать структуру в теле функции. Переменная локальная, какая разница вроде бы... оказалось что в elf при этом что-то приписывается такое, что не все его потом понимают. Нужен был протеус, а он не грузил файл... только описание структуры вынес - заработало.
Цитата
код на любом языке высокого уровня можно перенести, если есть компилятор, ну а на ассемблере нельзя

Псевдокод - можно! Если макросредства не меняются.
Golikov A.
напишите виндус ан ассемблере, а потом рассказывайте что С код труднее отлаживать...

описали структуру не так... так в ассемблере структуры вообще нет.
А реюзинг? А Класс с++?

С++ дает огромные преимущества в повторном использовании кода, правда конечно если вы не балуетесь перегрузкой сложения вычитанием, а вычитания сложением.

С, С++, ява, асемблер - это инструменты. Новые не появлялись бы если прошлые всех устраивали, но так же старые не оставались в строю, если бы новые делали все что надо. Правда как всегда по середине, но смещена в сторону частоты использования.

SII
Цитата(_Pasha @ Jan 18 2014, 01:09) *
Псевдокод - можно! Если макросредства не меняются.


Псевдокод будет уступать по эффективности родному ассемблеру конкретной архитектуры, поскольку, используя этот самый родной ассемблер, можно эффективно использовать особенности данной архитектуры, а псевдокод (если я правильно понял, что Вы имеете в виду) будет сродни языку высокого уровня -- представлять некие машинно-независимые абстракции, которые нужно транслировать в машинный код. Скажем, такая операция, как пересылка или сравнение последовательности байтов в двух областях памяти, на одной архитектуре потребует целой подпрограммы, на другой -- 2-3 инструкций, на третьей -- вообще одной инструкции, но при этом будут различаться требования к размещению адресов областей и т.д. Сделать эффективную трансляцию подобного с помощью макросов под любые архитектуры не получится -- всегда будут всплывать особенности и ограничения конкретных архитектур (скажем, на IA-32 эта задача формально решается одной инструкцией с префиксом повторения, однако исходные данные должны быть загружены в строго определённые регистры; на ARM требуется несколько команд, но зато можно пользоваться любыми регистрами, в Системе 360 и её потомках, включая современные мэйнфреймы, есть две инструкции для решения каждой из этих задач с разным способом указания областей памяти, и в разных случаях надо использовать одну из них, на VAX это решается одной инструкцией без каких-то особых ограничений и т.д.). Ну а поскольку одна из основных причин использования ассемблера заключается в получении большей эффективности, чем при кодировании той же задачи на каком-то ЯВУ, жертвовать ею ради такой "макропереносимости" смысла нет.

А вот в рамках одной архитектуры макросы очень сильно могут помочь. У меня, например, есть набор своих макросов, которые помогают эффективнее использовать язык ассемблера в зависимости от того, какой набор команд -- Thumb или Thumb-2 -- доступен, а также что из себя представляют операнды. Т.е. программа пишется частью обычными инструкциями (там, где разницы нет), частью такими макросами, а они внутри себя используют условную трансляцию, чтобы сформировать наиболее подходящую последовательность инструкций. Например, мой макрос MOVC загружает в регистр константу, при этом он может превратиться в инструкцию movs, movw или ldr в зависимости от значения константы и доступной системы команд. Ну а в тех случаях, когда макросы помочь не могут (из-за того, что задача уж очень специализированная), но нужно обеспечить переносимость под разные версии архитектуры, я уже сам явным образом использую условную трансляцию.
_Pasha
Цитата(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 элементов, иначе крыша счастливого программера вспухнет sm.gif
можем ввести псевдокод например 16-битный <0xFF><адрес-в-таблице-функций> как безусловное исполнение, ну там... несколько вариантов условных, объяснить кто куда данные поставляет. Это все в пределах 16 бит можно.

и цикл, который такую таблицу схавает, уже описать в виде макроса

Заметьте, ничего святого sm.gif никак микро-интерпретатор не претендует на роль глобальной системы. просто вкрапления. Не нравится такая система? Тут же конструируем и применяем другую. Регистров в контроллере многовато? ок, можно параллелить процессы с меньшим числом регистров.

портирование сводится ессно к реализации зоопарка таких штук.
megabuks
Добрый день
Что-бы не плодить темы. Помогите стартануть проект на 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?
Заранее спасибо
jcxz
Возьмите любой cstartup.asm (или как он там называется) из любого примера IAR для вашего ядра.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.