xvr 12 5 февраля, 2020 Опубликовано 5 февраля, 2020 · Жалоба 4 hours ago, jcxz said: Ну-ка - покажите класс - напишите на си код, который по эффективности будет хотя-бы сравним с: Кстати не факт, что ваш код эффективен - push и pop 4х регистров на входе/выходе может съесть больше, чем вы выиграли на жонглировании регистрами Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 5 февраля, 2020 Опубликовано 5 февраля, 2020 · Жалоба 3 hours ago, Forger said: Есть еще среди них упорные адепты этой старой "школы" Если говорить про меня, то я просто хочу получить новые знания. Программировать полностью на асме не заставляю ни кого. У нас уже есть один приверженец линукса))) Который навязывает его всем и вся. 1 hour ago, Forger said: но и аппаратно встроены в МК.... Не надо) 32 minutes ago, xvr said: Intel компилятор под x86 это умеет. Ну эти камешки я не программирую. 32 minutes ago, xvr said: Да и интристики никто не отменял Это, лишь, иная форма записи ассемблерных команд... 1 minute ago, xvr said: push и pop 4х регистров на входе/выходе может съесть больше, Дело не в жонглировании. Дело в этом. По стандарту о вызове функций, вы только r0-r3 можете не сохранять, изменять в функции, как угодно. При этом вызывающий код не должен расчитывать на их сохранность. Все остальные регистры вы обязаны восстановить при выходе из функции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 5 февраля, 2020 Опубликовано 5 февраля, 2020 · Жалоба 4 часа назад, xvr сказал: Кстати не факт, что ваш код эффективен - push и pop 4х регистров на входе/выходе может съесть больше, чем вы выиграли на жонглировании регистрами Если бы Вы хотя-бы что-то подтвердили фактами, т.е. - кодом, то Ваши слова имели бы какой-то вес. На представленные 3 примера Вы ничего не смогли предоставить, никакого фактического доказательства кроме пустых теоретизирований. Из чего делаю вывод, что в теме Вы не разбираетесь. PS: PUSH/POP каких-то регистров вообще не понимаю - к чему тут? 4 часа назад, haker_fox сказал: Это, лишь, иная форма записи ассемблерных команд... Вот именно... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 5 февраля, 2020 Опубликовано 5 февраля, 2020 · Жалоба 9 hours ago, jcxz said: вот другой пример: Есть код, который состоит из длинного полотенца: Мне кажется, Вы сильно загоняетесь. Решение в лоб: unsigned long vars[64]; #define PROC(B,T,N) \ if (mask&(1UL<<B)) {T *_d; _d=d; *_d++=vars[N]; d=_d;} void f(unsigned long mask, void *d) { PROC(0,long,0); PROC(1,short,1); PROC(2,long,2); PROC(3,long,3); PROC(4,short,4); PROC(5,short,5); PROC(6,long,6); PROC(7,short,7); } дает вполне вменяемый результат: Spoiler \ In section .bss, align 4 2 unsigned long vars[64]; \ vars: \ 0x0 DS8 256 3 4 #define PROC(B,T,N) \ 5 if (mask&(1UL<<B)) {T *_d; _d=d; *_d++=vars[N]; d=_d;} 6 \ In section .text, align 2, keep-with-next 7 void f(unsigned long mask, void *d) 8 { 9 PROC(0,long,0); \ f: (+1) \ 0x0 0x.... LDR.N R2,??DataTable1 \ 0x2 0x07C3 LSLS R3,R0,#+31 \ 0x4 0xBF44 ITT MI \ 0x6 0xF8D2 0xC000 LDRMI R12,[R2, #+0] \ 0xA 0xF841 0xCB04 STRMI R12,[R1], #+4 10 PROC(1,short,1); \ 0xE 0x0783 LSLS R3,R0,#+30 \ 0x10 0xBF44 ITT MI \ 0x12 0xF8D2 0xC004 LDRMI R12,[R2, #+4] \ 0x16 0xF821 0xCB02 STRHMI R12,[R1], #+2 11 PROC(2,long,2); \ 0x1A 0x0743 LSLS R3,R0,#+29 \ 0x1C 0xBF44 ITT MI \ 0x1E 0xF8D2 0xC008 LDRMI R12,[R2, #+8] \ 0x22 0xF841 0xCB04 STRMI R12,[R1], #+4 12 PROC(3,long,3); \ 0x26 0x0703 LSLS R3,R0,#+28 \ 0x28 0xBF44 ITT MI \ 0x2A 0xF8D2 0xC00C LDRMI R12,[R2, #+12] \ 0x2E 0xF841 0xCB04 STRMI R12,[R1], #+4 13 PROC(4,short,4); \ 0x32 0x06C3 LSLS R3,R0,#+27 \ 0x34 0xBF44 ITT MI \ 0x36 0xF8D2 0xC010 LDRMI R12,[R2, #+16] \ 0x3A 0xF821 0xCB02 STRHMI R12,[R1], #+2 14 PROC(5,short,5); \ 0x3E 0x0683 LSLS R3,R0,#+26 \ 0x40 0xBF44 ITT MI \ 0x42 0xF8D2 0xC014 LDRMI R12,[R2, #+20] \ 0x46 0xF821 0xCB02 STRHMI R12,[R1], #+2 15 PROC(6,long,6); \ 0x4A 0x0643 LSLS R3,R0,#+25 \ 0x4C 0xBF44 ITT MI \ 0x4E 0xF8D2 0xC018 LDRMI R12,[R2, #+24] \ 0x52 0xF841 0xCB04 STRMI R12,[R1], #+4 16 PROC(7,short,7); \ 0x56 0x0600 LSLS R0,R0,#+24 \ 0x58 0xBF44 ITT MI \ 0x5A 0x69D2 LDRMI R2,[R2, #+28] \ 0x5C 0x800A STRHMI R2,[R1, #+0] 17 } \ 0x5E 0x4770 BX LR ;; return Тут, конечно, может возникнуть вопрос другого характера. Например, если почти все параметры используются, то грузить их в регистры при помощи LDM будет малость эффективнее. А вот у IAR'а с использованием LDM как-то не сложилось, черт его знает, почему. Но возможен другой вариант. Допустим, что из всего списка в реальности надо вообще всего пару-тройку параметров генерить. Тогда куда более эффективным решением будет такое: typedef void (*FillFunc)(void *, void *, long *); #define GLUE(A,B) A##B #define FillParam(T,N) \ void GLUE(FillParam,N)(void *functab, void *d, long *s) \ { \ T *_d; \ _d=d; \ *_d++=s[N]; \ FillFunc *_functab=functab; \ FillFunc nf=*_functab++; \ nf(_functab,_d,s); \ } FillParam(long,0) FillParam(short,1) FillParam(long,2) FillParam(short,3) void FillParamEnd(void *functab, void *d, long *s) { } FillFunc FillerTask[]= { FillParam0,FillParam1,FillParam2,FillParam3, FillParamEnd }; void FillParamBegin(void *d, long *s) { FillFunc *functab=FillerTask; FillFunc nf=*functab++; nf((void*)functab,d,s); } Результат как на асме: Spoiler 19 typedef void (*FillFunc)(void *, void *, long *); 20 21 #define GLUE(A,B) A##B 22 23 #define FillParam(T,N) \ 24 void GLUE(FillParam,N)(void *functab, void *d, long *s) \ 25 { \ 26 T *_d; \ 27 _d=d; \ 28 *_d++=s[N]; \ 29 FillFunc *_functab=functab; \ 30 FillFunc nf=*_functab++; \ 31 nf(_functab,_d,s); \ 32 } 33 \ In section .text, align 2, keep-with-next 34 FillParam(long,0) \ FillParam0: (+1) \ 0x0 0x6813 LDR R3,[R2, #+0] \ 0x2 0xF841 0x3B04 STR R3,[R1], #+4 \ 0x6 0xF850 0x3B04 LDR R3,[R0], #+4 \ 0xA 0x4718 BX R3 \ In section .text, align 2, keep-with-next 35 FillParam(short,1) \ FillParam1: (+1) \ 0x0 0x6853 LDR R3,[R2, #+4] \ 0x2 0xF821 0x3B02 STRH R3,[R1], #+2 \ 0x6 0xF850 0x3B04 LDR R3,[R0], #+4 \ 0xA 0x4718 BX R3 \ In section .text, align 2, keep-with-next 36 FillParam(long,2) \ FillParam2: (+1) \ 0x0 0x6893 LDR R3,[R2, #+8] \ 0x2 0xF841 0x3B04 STR R3,[R1], #+4 \ 0x6 0xF850 0x3B04 LDR R3,[R0], #+4 \ 0xA 0x4718 BX R3 \ In section .text, align 2, keep-with-next 37 FillParam(short,3) \ FillParam3: (+1) \ 0x0 0x68D3 LDR R3,[R2, #+12] \ 0x2 0xF821 0x3B02 STRH R3,[R1], #+2 \ 0x6 0xF850 0x3B04 LDR R3,[R0], #+4 \ 0xA 0x4718 BX R3 38 \ In section .text, align 2, keep-with-next 39 void FillParamEnd(void *functab, void *d, long *s) 40 { 41 } \ FillParamEnd: (+1) \ 0x0 0x4770 BX LR ;; return 42 \ In section .data, align 4 43 FillFunc FillerTask[]= \ FillerTask: \ 0x0 0x....'.... DC32 FillParam0, FillParam1, FillParam2, FillParam3, FillParamEnd \ 0x....'.... \ 0x....'.... \ 0x....'.... \ 0x....'.... 44 { 45 FillParam0,FillParam1,FillParam2,FillParam3, 46 FillParamEnd 47 }; 48 \ In section .text, align 2, keep-with-next 49 void FillParamBegin(void *d, long *s) 50 { \ FillParamBegin: (+1) \ 0x0 0x460A MOV R2,R1 51 FillFunc *functab=FillerTask; 52 FillFunc nf=*functab++; 53 nf((void*)functab,d,s); \ 0x2 0x.... LDR.N R3,??DataTable1_1 \ 0x4 0x4601 MOV R1,R0 \ 0x6 0x1D18 ADDS R0,R3,#+4 \ 0x8 0x681B LDR R3,[R3, #+0] \ 0xA 0x4718 BX R3 54 } Естественно, FillerTask можно сгенерить с нужной Вам периодичностью из редко изменяемой маски. Ну и, конечно, возможна вообще циничная генерация самомодифицирующегося кода из команд LDR R2,[R0,#+disp] и STR(H) R2,[R1],#4(2). Его генерация отлично на Си пишется. И как бы не смешно это звучало, но это будет самый оптимальный вариант (ну, правда, максимум может понадобится 64*6+2=386 байт ОЗУ для хранения генерируемого кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 5 февраля, 2020 Опубликовано 5 февраля, 2020 · Жалоба Кстати, господа, пардон во втором примере за безумные приведения к FiiFunc*, но я просто не соображу, можно ли описать тип указателя на функцию, в которой один из параметров - указатель на такую функцию. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 5 февраля, 2020 Опубликовано 5 февраля, 2020 · Жалоба Продолжаем разговор ;) 11 hours ago, jcxz said: Есть массив из 512-и 16-битных беззнаковых чисел. Нужно найти максимальное число в этом массиве. Вот тут я бы пересмотрел вообще саму идеологию. Все эти прямые поиски - они все равно O(N), хоть на асме, хоть на Си. Как данные в массив попадают? Может быть их имеет смысл как-то предсортировать, если они попадают в массив малыми порциями, и этим вообще глобально улучшить ситуацию? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба 9 часов назад, Rst7 сказал: Вот тут я бы пересмотрел вообще саму идеологию. Все эти прямые поиски - они все равно O(N), хоть на асме, хоть на Си. Как данные в массив попадают? Может быть их имеет смысл как-то предсортировать, если они попадают в массив малыми порциями, и этим вообще глобально улучшить ситуацию? Как конкретно - не знаю. Эту задачу тут не так давно кто-то озвучивал. Попадать могут например из АЦП->DMA и не малой порцией, а сразу всем блоком = 512 сэмплов. И как в этом случае обойтись без асма? 10 часов назад, Rst7 сказал: Решение в лоб: Решение "в лоб" очень неоптимальным получается. Цитата Тут, конечно, может возникнуть вопрос другого характера. Например, если почти все параметры используются, то грузить их в регистры при помощи LDM будет малость эффективнее. Через LDM невозможно, так как переменные var0, ... раскиданы в памяти произвольным образом. varX - это условно так обозначено, чтобы описать задачу. А в общем случае - это могут быть и отдельные члены разных классов или структур. Цитата Но возможен другой вариант. Допустим, что из всего списка в реальности надо вообще всего пару-тройку параметров генерить. Да, в реале так может быть. Даже в bm может быть установлен всего один бит==1. Даже - собственно количество единичных битов там ограничено неким небольшим числом. И обычно их мало единиц там. Цитата Ну и, конечно, возможна вообще циничная генерация самомодифицирующегося кода из команд LDR R2,[R0,#+disp] и STR(H) R2,[R1],#4(2). Его генерация отлично на Си пишется. И как бы не смешно это звучало, но это будет самый оптимальный вариант Ну вот именно так я и решил эту задачу! Самомодифицирующимся кодом. Получилось выполнение такого кода значительно быстрее чем классического со множеством условных веток. Не важно на чём он генерится, но результирующая функция будет на асме. И без знания ассемблера её не напишешь. О чём и идёт разговор в этом треде. Цитата (ну, правда, максимум может понадобится 64*6+2=386 байт ОЗУ для хранения генерируемого кода. ОЗУ там нужно не только для хранения кода, но и для хранения таблицы адресов переменных. Функция генерящая код, генерит и таблицу адресов переменных. И выглядит это не совсем так как Вы написали, а как три команды: LDR Rx, [PC, #...] ;загрузка адреса переменной LDR[H] Rx, [Rx] ;загрузка значения переменной STR[H] Rx, [Ry], #4 или #2 ;запись значения Примерно так. С вычислением смещения от PC до нужного индекса таблицы адресов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба 10 hours ago, Rst7 said: Ну и, конечно, возможна вообще циничная генерация самомодифицирующегося кода из команд LDR R2,[R0,#+disp] и STR(H) R2,[R1],#4(2). Склоняю голову... ибо ничего не понимаю((( Если можно, поясните "на пальцах". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба 10 часов назад, Rst7 сказал: Кстати, господа, пардон во втором примере за безумные приведения к FiiFunc*, но я просто не соображу, можно ли описать тип указателя на функцию, в которой один из параметров - указатель на такую функцию. Вариант в лоб с кучей функций вызываемых через указатели - это пожалуй самый тормозной будет. Из-за огромного количества переходов. Классическое ветвление на операторах условного выполнения - и то гораздо лучше. Даже не рассматривал такой вариант. 3 минуты назад, haker_fox сказал: Склоняю голову... ибо ничего не понимаю((( Если можно, поясните "на пальцах". Я про эту задачу тут уже как-то писал. Тема называлось по-моему как-то "Полиморфный код" что-ли. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба 52 minutes ago, jcxz said: Вариант в лоб с кучей функций вызываемых через указатели - это пожалуй самый тормозной будет. Нет, если установленных в 1 бит немного. Куда быстрее, чем куча if'ов. 1 hour ago, jcxz said: Через LDM невозможно, так как переменные var0, ... раскиданы в памяти произвольным образом. varX - это условно так обозначено, чтобы описать задачу. А в общем случае - это могут быть и отдельные члены разных классов или структур. Простите, а кто вообще этот протокол обмена придумал? Зачем такие безумные сложности? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 189 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба 2 часа назад, haker_fox сказал: Склоняю голову... ибо ничего не понимаю((( Если можно, поясните "на пальцах". Как было отмечено, не так давно все это оговаривалось 12 часов назад, Rst7 сказал: Все эти прямые поиски - они все равно O(N), хоть на асме, хоть на Си. В Cortex-M4 есть инструкции, которые могут за один проход сравнить соответствующие полуслова в двух регистрах или группу по 4 байта в двух регистрах Хотя это больше к вопросу о равномерности времени выполнения функции поиска, (детерминированности, что ли)... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба 15 minutes ago, Arlleex said: В Cortex-M4 есть инструкции, которые могут за один проход сравнить соответствующие полуслова в двух регистрах или группу по 4 байта в двух регистрах Хотя это больше к вопросу о равномерности времени выполнения функции поиска, (детерминированности, что ли)... Это же и есть O(N). Т.е. время будет пропорционально количеству отсчетов. Коэффициент пропорциональности зависит от оптимизации в том числе, но куда полезнее подумать о возможности переделать алгоритм так, чтобы он превратился, например, в O(log2(N)). Думать надо вот в какую сторону - поиск максимума в отсортированном массиве - O(1). Можно считать - бесплатно. Прямой поиск - O(N). Возможно есть какие-то априорные знания о массиве, какие-то способы предсортировки данных, etc Просто может так оказаться, что завтра N будет равно не 512, а 4096, и никакой прямой поиск, написанный на ассемблере, не спасет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба 16 hours ago, jcxz said: Если бы Вы хотя-бы что-то подтвердили фактами, т.е. - кодом, то Ваши слова имели бы какой-то вес. На представленные 3 примера Вы ничего не смогли предоставить, никакого фактического доказательства кроме пустых теоретизирований. Из чего делаю вывод, что в теме Вы не разбираетесь. Оригинальный вывод. Из того, что я не собираюсь тратить своё время на написание не нужного мне кода, вы делаете вывод - 'что в теме Вы не разбираетесь' 16 hours ago, jcxz said: PS: PUSH/POP каких-то регистров вообще не понимаю - к чему тут? PUSH {R4 - R7, LR} POP {R4 - R7, PC} За сим беседы с вами прекращаю, за бесперспективностью - код я вам не приведу (могу от x86, но он вас не устроит), а слова вас не убеждают :( Да и Факты у вас весьма оригинальные - интересен не АСМ код, а время его выполнения, и не сам по себе, а в сравнении с С версией. Этого вы не привели, из чего я делаю вывод, что фактов у вас тоже нет, как это не парадоксально Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 189 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба Темы asm vs C, Windows vs Linux, AVR vs PIC, видимо, никогда не прекратятся на этом Форуме (да вообще нигде) Все равно каждый останется при своем мнении, основываясь на фактах, полученных из личного опыта. И каждый будет по-своему прав. ИМХО, невозможно говорить что есть правильно, а что нет. Кому-то деньги позволяют при узком горле в производительности взять и уйти на другой камень. А кто-то должен из 8-битного МК вытянуть все возможное, потому что стоит копье или еще какая причина (а-ля исторически юзает компания допотопный AVR, и грозное консервативное начальство не сломить модными 32-битными архитектурами). Да в чем вообще проблема? Не было необходимости лезть в листинг? Да не лезь - это же замечательно! Как будто насильно заставляет кто-то использовать этот несчастный ассемблер, ей-богу Сентенции вслух без конкретного адресата, шоб ненароком не обидеть никого Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 6 февраля, 2020 Опубликовано 6 февраля, 2020 · Жалоба 4 часа назад, Rst7 сказал: Простите, а кто вообще этот протокол обмена придумал? Зачем такие безумные сложности? А где здесь протокол? А придумала это жизнь. Нужно было сделать осциллографирование (в реальном времени) содержимого некоторых переменных в ПО. Переменные разбросаны по всей ОЗУ. Есть конечный список переменных (всего <=64шт), одновременно может быть выбрано не более чем N (зависящее от размера выходного пакета). И эта функция частотой сэмплирования (const) собирает содержимое переменных в единый кадр. Который потом улетает в интерфейс связи. А как ещё такое можно оптимально реализовать? Предложения? Загрузка CPU этим кодом должна быть минимальной. 2 часа назад, Rst7 сказал: Думать надо вот в какую сторону - поиск максимума в отсортированном массиве - O(1). Можно считать - бесплатно. Прямой поиск - O(N). Возможно есть какие-то априорные знания о массиве, какие-то способы предсортировки данных, etc Я Вам уже приводил пример - Вы так ничего и не ответили на него: Например - данные поступают от АЦП. И как заставить АЦП присылать уже отсортированные данные, расскажите? 1 час назад, xvr сказал: PUSH {R4 - R7, LR} POP {R4 - R7, PC} И...? К чему это? Как это относится к теме??? Цитата За сим беседы с вами прекращаю, за бесперспективностью - код я вам не приведу (могу от x86, но он вас не устроит), а слова вас не убеждают :( Пустые слова - не убеждают. Цитата Да и Факты у вас весьма оригинальные - интересен не АСМ код, а время его выполнения, и не сам по себе, а в сравнении с С версией. Этого вы не привели Что я не привёл?? Поднимите глаза выше. Я приводил примеры кода на ассемблере, спрашивал как это сделать на си, чтобы после компиляции получалось хотя-бы не хуже - Вы слились, молча. Приводил код на си, спрашивал как получить оптимальное время выполнения того кода, не зная ассемблера - тоже слились. Если не разбираетесь в теме, зачем тогда вообще писать? Вот этого не понимаю. Пустыми словами тут никого не убедишь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться