Easyelectronics.ru

Электроника для всех
Текущее время: 22 сен 2019, 17:38

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/10pcs (Любой цвет!)
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 22 ] 
Автор Сообщение
 Заголовок сообщения: Аналог сишного return в ассемблере
СообщениеДобавлено: 29 июн 2015, 15:49 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
Всем добра! Понадобилось мне реализовать на ассемблере пару функций, одна читает из параллельного порта данные, а другая туда пишет. Ту функцию, которая пишет туда данные, я реализовал
Код:
.text
  .syntax unified
  .global __write
  .type __write, function

  .equ ADDR,           0x50000000
  .equ DATA,           0x50000002

  .thumb
  __write:
 
  push  {r3, r4}

  ldr   r3,  =ADDR
  ldr   r4,  =DATA

  strh  r0, [r3]
  strh  r1,  [r4]

  pop   {r3, r4}
  bx    lr
.end

и её можно вызывать в программе на Си примерно так
Код:
__write(0x1000, 0x5555); /** 0x1000 - адрес, 0x5555 - данные */

если я конечно ничего не напутал, но вроде первый аргумент автоматически заноситься в регистр r0, второй в r1 и т.д.
Но как сделать аналогичную функцию, только которая будет читать данные? Точнее я не знаю, как возвратить значение из неё, чтобы (допустим функция назовётся __read(address)) я смог в программе на Си вызвать её примерно так
Код:
uint16_t data = __read(0x1000); /** 0x1000 - это адрес, с которого прочитано значение и записано в переменную data */

а остальное (прочитать значение и записать его в регистр) вроде смогу реализовать сам, поэтому задачу в неком приближении можно рассмотреть таким образом.
Есть какой-нибудь регистр (допустим r1), и надо, чтобы функция возвратила его.

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 29 июн 2015, 15:56 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2619
Откуда: Санкт-Петербург
Погуглите "calling convention" для своего компилятора (или вообще поищите в доках). Вроде обычно для gcc/arm возвращаемое значение ожидается в r0 (или в паре r0-r1): https://en.wikipedia.org/wiki/Calling_c ... _.28A32.29


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 29 июн 2015, 16:12 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
aamonster писал(а):
Вроде обычно для gcc/arm возвращаемое значение ожидается в r0 (или в паре r0-r1)

ах да, забыл указать, что компилятор GCC и проц Cortex-M3.

Если я всё верно догнал, то чтобы сделать такую функцию, как описал в первом посте, то достаточно просто поместить результат в регистр r0.

Спасибо большое, пошёл тестить:)

Ах нет, ещё пару вопросов, если можно:)

Первый, можно ли объявить две функции таким образом в одном файле?

Код:
.text
  .syntax unified
  .global __write, __read
  .type __write, function
  .type __read, function

  .equ ADDR,           0x50000000
  .equ DATA,           0x50000002

  .thumb
  __write:
 
  push  {r3, r4}

  ldr   r3,  =ADDR
  ldr   r4,  =DATA

  strh  r0, [r3]
  strh  r1,  [r4]

  pop   {r3, r4}
  bx    lr
 
  __read:
 
  push  {r3, r4}
 
  strh  r0,  [r3] ;; ADDRESS
  ldrh  r0,  [r4] ;; in r0 = result
 
  pop   {r3, r4}
  bx    lr
.end


и второй:
если функция принимает один аргумент, и возвращает одно значение, то получается, что и принимаемый аргумент в регистре r0 и возвращаемое значение тоже ожидается в r0?

и третий:
перед функцией обязательно используемые регистры (в данном случае r3 и r4) помещать в стек? и надо ли помещать в стек регистры r0 и r1?

З.Ы. Пардон, если задал много глупых вопросов:)

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 29 июн 2015, 16:21 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2619
Откуда: Санкт-Петербург
Я же не настоящий сварщик, маску на стройке нашёл (в смысле, на ARM не пишу, просто заглянул в описание CC, чтобы подсказать, где искать).
Но вроде 1 - можно, 2 - именно так, 3 - опять же, почитайте свою CC (какие-то регистры можно не сохранять - "Subroutines must preserve the contents of r4 to r11 and the stack pointer"), лучше не в wiki, а в доках от компилятора.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 29 июн 2015, 19:57 
Старожил

Зарегистрирован: 22 мар 2010, 22:54
Сообщения: 3995
а можно поинтересоваться, зачем ассемблер, если вызывать все равно из си?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 29 июн 2015, 21:17 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2619
Откуда: Санкт-Петербург
Кстати да. Если эти функции написать на Си и объявить inline - оптимизатор их вроде должен сделать ничуть не хуже ассемблерных...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 29 июн 2015, 21:54 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
aamonster писал(а):
Но вроде 1 - можно, 2 - именно так, 3 - опять же, почитайте свою CC

вроде что-то работает, как точно удостоверюсь, что всё ок, примерчик рабочий выложу:)

Насчёт этого
Ink писал(а):
а можно поинтересоваться, зачем ассемблер, если вызывать все равно из си?

и этого
aamonster писал(а):
Кстати да. Если эти функции написать на Си и объявить inline - оптимизатор их вроде должен сделать ничуть не хуже ассемблерных...

то тут несколько моментов.
Первый - мне важно знать, сколько тактов выполняется у меня тот или иной кусок кода, т.к. временные интервалы примерно в десятки наносекунд.
Второй - замечено, что компилятор (GCC 4.9.3 c -O3) инлайн-функцию (отмеченную через __attribute__( (always_inline) ) inline func() )всё равно некоторые вещи делает/оптимизирует или в лучшую, или в худшую сторону, предугадаешь не всегда. Поэтому я всякие критичные куски кода пишу на ассемблере, чтобы точно знать, что компилятор ничего там не заоптимизирует за меня:) или может просто я рукожоп :)
Ну и третий - это то, что мне надо работать довольно с большими объёма данными, а наши бравые отечественные производители в виде Миландра, запихали зачем-то в контроллер кривой свой ускоритель флешки, из-за которого получается разное время доступа к различным участкам памяти. Поэтому ещё приходится лепить велосипед, чтобы расфасовать данные по одинаковым банкам флешки, чтоб ускоритель флешки даже и не пытался работать. И это всё безобразие должно работать очень быстро (насколько позволяет не менее тормозная периферия), поэтому и там тоже ассемблер, чтоб исключить ещё косяки оптимизации компилятора :)

P.S. Ещё немного, и смогу каждого инвалида снабдить уникальным костылём :)

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 29 июн 2015, 22:35 
Старожил

Зарегистрирован: 22 мар 2010, 22:54
Сообщения: 3995
Alisa писал(а):
Первый - мне важно знать, сколько тактов выполняется у меня тот или иной кусок кода, т.к. временные интервалы примерно в десятки наносекунд.
кол-во тактов может быть не равно кол-ву команд и зависеть от много чего.
Alisa писал(а):
Второй - замечено, что компилятор (GCC 4.9.3 c -O3) инлайн-функцию (отмеченную через __attribute__( (always_inline) ) inline func() )всё равно некоторые вещи делает/оптимизирует или в лучшую, или в худшую сторону, предугадаешь не всегда.
так-то компилятор может еще учитывать конвейеры, не сбрасывать их на бранчах (когда инлайн), ничего за зря не пихать в стек и т.д. имхо, у вас при нынешнем подходе будет тупо больше вспомогательных команд.

но если надо будет какие-то другие большие функции ускорять, тогда может и будет смысл...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 30 июн 2015, 01:33 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 23 мар 2012, 16:18
Сообщения: 146
Alisa писал(а):
Первый - мне важно знать, сколько тактов выполняется у меня тот или иной кусок кода, т.к. временные интервалы примерно в десятки наносекунд.

Десятки наносекунд... разве это частотой камня, скажем в 100 МГц, не достигается на С++?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 30 июн 2015, 03:20 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2619
Откуда: Санкт-Петербург
zat, я так понял, он хочет руками посчитать такты и не думать, что завтра компилятор изменится и сможет соптимизировать на такт лучше.

Хотя интуитивно чувствую, что ARM в этом плане даже на асме не надо доверять :-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 30 июн 2015, 03:51 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 23 мар 2012, 16:18
Сообщения: 146
Просто речь вроде о параллельном порте шла, а там максимальная скорость по стандарту всего лишь около 2.5 Мбит/с (ECP+DMA).
С++ тут вроде справляется даже со всякими оптимизациями. Нет разве ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 30 июн 2015, 07:12 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 янв 2010, 18:55
Сообщения: 163
Откуда: Томск
Не совсем по теме, но вот тут есть статья про ассемблер, встраиваемый в сишный код:
http://www.ethernut.de/en/documents/arm-inline-asm.html

Мне в свое время эта статья помогла прояснить некоторые моменты.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 30 июн 2015, 23:07 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
Ink писал(а):
кол-во тактов может быть не равно кол-ву команд и зависеть от много чего.

если делать вывод, исходя из написанных команд, то да. Но если смотреть, исходя из object dump, то можно точно знать, сколько тактов выполняется тот, или иной код.
Ink писал(а):
так-то компилятор может еще учитывать конвейеры, не сбрасывать их на бранчах (когда инлайн), ничего за зря не пихать в стек и т.д. имхо, у вас при нынешнем подходе будет тупо больше вспомогательных команд.

у меня часть кода на Си, а на ассемблере участки, которые должны работать быстро и за указанное время.
А так, позже гляну бинарник, посмотрю, что она туда подобавлял. Хотя, когда просматривал ассемблерный листинг, из которого компилятор уже собирает объектный файл, там всё чисто, и без всяких дополнительных команд. Только написанная на ассемблере функция выглядит более лаконично ;)
zat писал(а):
Просто речь вроде о параллельном порте шла, а там максимальная скорость по стандарту всего лишь около 2.5 Мбит/с (ECP+DMA).
С++ тут вроде справляется даже со всякими оптимизациями. Нет разве ?

нет, не совсем:) к примеру, у меня программа на ассемблере передаёт 48 бит за 504нс, а программа на Си тратила около микросекунды. И уже эта микросекунда лишь с большой натяжкой устраивала меня
zat писал(а):
Десятки наносекунд... разве это частотой камня, скажем в 100 МГц, не достигается на С++?

может и достигается, С++ не пробовал, у меня почти весь код на С. Но не просто так же я решил переписывать код с Си на ассемблер:) к тожу, как я уже указывал, камень у меня немного дурновой (отечественный ARM с ядром Cortex-M3, работающий на 80МГц). Который даже ногой быстрее 112нс дёргать не может.
Ну а в целом, в некоторых местах, переписывание на ассемблер подняло производительность примерно на 40-50% (например запись множества циферок в параллельную шину)
aamonster писал(а):
Хотя интуитивно чувствую, что ARM в этом плане даже на асме не надо доверять :-)

почему же не надо? Просто помимо того, что смотреть в код, который пишешь, ещё и смотреть в бинарник, который тебе даёт компилятор:) и нём посчитать такты, количество команд и пр. не составит труда:)

dmk793 спасибо за статью:) тоже читал её где-то, когда ассемблерные вставки делал в коде:)

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 01 июл 2015, 10:50 
Старожил

Зарегистрирован: 27 мар 2015, 01:22
Сообщения: 1432
Alisa писал(а):
aamonster писал(а):
Хотя интуитивно чувствую, что ARM в этом плане даже на асме не надо доверять :-)

почему же не надо? Просто помимо того, что смотреть в код, который пишешь, ещё и смотреть в бинарник, который тебе даёт компилятор:) и нём посчитать такты, количество команд и пр. не составит труда:)

Предчувствия его не обманули ) http://infocenter.arm.com/help/index.js ... BCJII.html - смотреть "бинарник" (hex-код инструкций в листинге?) бесполезно. Кроме того, армовый ассемблер сам выбирает из нескольких возможных кодировок инструкций какую захочет, сам заменяет инструкции на эквивалентные, которые ему больше нравятся, и даже сам создаёт литеральный пул констант, если константа не помещается в код инструкции. А gnu ассемблер разных версий ещё и по разному это делает.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 01 июл 2015, 13:09 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
vt340 писал(а):
Предчувствия его не обманули ) http://infocenter.arm.com/help/index.js ... BCJII.html - смотреть "бинарник" (hex-код инструкций в листинге?) бесполезно. Кроме того, армовый ассемблер сам выбирает из нескольких возможных кодировок инструкций какую захочет, сам заменяет инструкции на эквивалентные, которые ему больше нравятся, и даже сам создаёт литеральный пул констант, если константа не помещается в код инструкции. А gnu ассемблер разных версий ещё и по разному это делает.

я вам вот про что хочу сказать.
Допустим, есть бинарник test
я делаю
arm-none-eabi-objdump -d ./test > infa.txt
и в файле infa.txt можно посмотреть, что именно будет выполнять проц.
например, функции записи и чтения для параллельной шины выглядят вот так
видно, что функции уложились в 7 инструкций.
Код:
080000c0 <dds_write>:
80000c0:       b430            push    {r4, r5}
80000c2:       4c1a            ldr     r4, [pc, #104]  ; (800012c <dds_software_reset+0x18>)
80000c4:       4d1a            ldr     r5, [pc, #104]  ; (8000130 <dds_software_reset+0x1c>)
80000c6:       8020            strh    r0, [r4, #0]
80000c8:       8029            strh    r1, [r5, #0]
80000ca:       bc30            pop     {r4, r5}
80000cc:       4770            bx      lr

080000ce <dds_read>:
80000ce:       b430            push    {r4, r5}
80000d0:       4c16            ldr     r4, [pc, #88]   ; (800012c <dds_software_reset+0x18>)
80000d2:       4d17            ldr     r5, [pc, #92]   ; (8000130 <dds_software_reset+0x1c>)
80000d4:       8020            strh    r0, [r4, #0]
80000d6:       8828            ldrh    r0, [r5, #0]
80000d8:       bc30            pop     {r4, r5}
80000da:       4770            bx      lr


я не отрицаю, что есть операции, зависящие от конкретных моментов, например, добавление/извлечение из стека. Но как правило, такие команды тоже можно посчитать, сколько тактов они делаются, т.к. всё нужное для расчёта известно. (известна предыдущая команда, суффикс команды, количество команд и т.д., вообщем всё огонь:) единственное, в случае какой-либо аномалии, посмотреть на конвейер)

Я ни кому не навязываю использовать асм вместо Си, просто для ряда задач, контролировать поведение программы проще именно на асм нежели на Си. Немаловажен тот факт, что компилятор оптимизирует лишь код на С, а код на асм оставляет без изменений. Конечно, могут заметить, что оптимизацию в С можно выключить, использовав volatile, но в этом случае опять же, получаем медленный код на С.
Ну а если задача мигать светодиодом, тот тут можно реализовывать на чём угодно;)

Ну это всё несколько не по теме конечно, ответ на вопрос я получил, спасибо большое за помощь, как протестирую, отпишусь, м.б. кому полезно будет :)

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 01 июл 2015, 14:24 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2619
Откуда: Санкт-Петербург
Ну, моё "недоверие" - это просто привычка, что на intel, начиная эдак с 80386, подсчёт тактов - крайне неблагодарное дело, т.к. могут вылезти всякие сложности типа cache misses (и один и тот же кусок кода в разных условиях пройдёт за разное число тактов). А ARM я скорее воспринимаю, как что-то сложное вроде современных интелов, чем как 8080 :-).

На ARM, кстати, время доступа к памяти не может варьироваться, скажем, в зависимости от работы DMA параллельно с CPU? (спрашиваю чисто из любопытства, так что перекапывать ради этого знания даташиты лень).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 01 июл 2015, 15:32 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
Просто "недоверию" есть вполне обоснованные причины, например команды которые выполняются не один такт, но они, как уже написал выше, вполне нормально расчитываются. Аналогичное "недоверие" можно и применить к С/С++, но с несколько более весомыми аргументами:)
aamonster писал(а):
На ARM, кстати, время доступа к памяти не может варьироваться, скажем, в зависимости от работы DMA параллельно с CPU? (спрашиваю чисто из любопытства, так что перекапывать ради этого знания даташиты лень).

Насчёт связки DMA и CPU сказать ничего не могу, максимум, если они обращаются к одному и тому же банку памяти на флешке (скорее всего этот пример больше "теоретический"). А так, сталкивался с разной скоростью доступа в памяти в таком случае. Была флеш в контроллере на 128Кб, которая разделена на 4 банка по 32Кб. Все банки были объедены в одно адресное пространство, таким образом при записи, допустим 128 бит, первые 32 бита, например попали в банк 1, следующие 32 - в банк 2 и т.д. И, был замечен такой косяк (в 1986ВЕ91Т), что если, допустим расположить данные в одном банке, то скоростью доступа постоянна, а если один расположены в разных банках (как раз это конфигурация по умолчанию), то доступ к двум из четырёх банков уменьшалась на 50нс. На форуме Миландра сказали, что во всём виноват ускоритель флешки, а мне пришлось городить костыли. Вот такой вот пример:)

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 02 июл 2015, 00:20 
Старожил

Зарегистрирован: 22 мар 2010, 22:54
Сообщения: 3995
Alisa писал(а):
На форуме Миландра сказали, что во всём виноват ускоритель флешки
вот именно поэтому стоит избегать подсчета тактов на процах типа арм.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 02 июл 2015, 01:55 
Старожил

Зарегистрирован: 04 янв 2014, 01:30
Сообщения: 208
Alisa писал(а):
На форуме Миландра сказали


Извините не в тему: добро пожаловать в клуб))) С большим интересом начинал работу с Миландром, а под конец как-то грустно стало((( Вроде м4Ф готовят уже, но грустно от двух таймеров и т.п. (переферия очень скудная)... а так хотелось)))


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 04 июл 2015, 14:00 
Заглядывает иногда

Зарегистрирован: 22 авг 2014, 12:29
Сообщения: 142
А у Миландра есть блок DWT ??? Если есть можно очень точно посмотреть сколь выполняется кусок кода с помощью этого блока .


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 04 июл 2015, 19:02 
Старожил

Зарегистрирован: 22 мар 2010, 22:54
Сообщения: 3995
EugenPKH писал(а):
Если есть можно очень точно посмотреть сколь выполняется кусок кода с помощью этого блока .
даже если, то завтра миландр выпустит новую ревизию чипа и времянки могут полететь.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Аналог сишного return в ассемблере
СообщениеДобавлено: 03 окт 2015, 02:13 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
Кстати, обещал код выложить, но всё не выкладывал. Нехорошо:)
Вообщем, вот код, оформленный в виде небольшой библиотеки для работы с DDS 1508ПЛ8Т. Написан на ассемблере, может быть кому-нибудь пригодится:)
https://bitbucket.org/kirra-cat/api1508pl8t

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 22 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB