Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 16:59:24

но я так и не пойму, зачем это делать :(

Чтобы процесс передачи-приема данных со стороны main был, как в HAL-библиотеках. Шмякнул функцию, получил ответ в тупом и однозначном виде (и не приходится заглядывать внутрь того ужаса, что понаписали программисты этой библиотеки). Вот тут советуют, что принято это делать через структуры.

ПростоНуб писал(а):Reflector, , исходя из того, что функция в C может возвращать структуру (не указатель на структуру, а именно структуру), то вернуть она может таким образом произвольное количество данных, причем даже различного типа.
В данном случае, использование структуры тоже упростило бы код.

Спасибо за наводку, сейчас сил наберусь новых и попробую тоже.

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 17:09:59

С -O2 бинарники получились абсолютно одинаковые, а с -O0 этот вариант меньше на 64 байта...

...и что?

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 17:37:49

...и что?

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

Добавлено after 4 minutes 12 seconds:
Reflector, , исходя из того, что функция в C может возвращать структуру (не указатель на структуру, а именно структуру), то вернуть она может таким образом произвольное количество данных, причем даже различного типа.
В данном случае, использование структуры тоже упростило бы код.

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

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 17:42:52

Как минимум то, что без оптимизатора компилятору никакие соглашения о вызове не помогли, там 64 байта разница между реализациями, а полный код еще в 2 раза больше. И наоборот, с оптимизатором для разных подходов получился одинаковый бинарник, т.е. в первую очередь дело именно в нем.
Да, Кэп, никто и не спорил, что оптимизатор делает код меньше. Вопрос был о другом.

PS: И когда хотите сравнить да результата компиляции, то делать это нужно всё-таки по листингу, рассматривая ассемблерные команды. А не по каким-то отвлечённым размерам чего-то не пойми чего...

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 17:52:15

Reflector, строго говоря, у Вас возвращается объект класса std::pair, содержащий пару объектов класса void*, конструируемый и инициализируемый внутри вызываемой функции. Вообще классически, надо было тогда создать еще и класс наследник std::pair с нужным методом, а не функцию :)
Я не пытаюсь спорить, что при правильной оптимизации, компилятор и для Вашего варианта, и для моего, сформирует одинаковый машинный код. Но идеологически - это разные решения. Мое - структурное, для С, Ваше - объектно-ориентированное, для C++. Я же не критикую Ваш вариант. Я только указал, что и средствами C он легко реализуется. А уж выберет ТС C или C++ - его дело.

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 18:05:05

Да, Кэп, никто и не спорил, что оптимизатор делает код меньше. Вопрос был о другом.

PS: И когда хотите сравнить да результата компиляции, то делать это нужно всё-таки по листингу, рассматривая ассемблерные команды. А не по каким-то отвлечённым размерам чего-то не пойми чего...

Раз:
Спойлер
Код:
uint64_t func()
{
   void* ptr1 = &var1;
   void* ptr2 = &var2;

   return (uint32_t)ptr1 | (uint64_t)ptr2 << 32;
}

uint64_t q = func();
void* ptr1 = (void*)(uint32_t)q;
void* ptr2 = (void*)(uint32_t)(q >> 32);

И два:
Спойлер
Код:
bl 0x8000914 <func()>
movs r3, r0
movs r4, r1
movs r2, #166
lsls r2, r2, #2
adds r1, r7, r2
str r3, [r1, #0]
str r4, [r1, #4]
adds r3, r7, r2
ldr r3, [r3, #0]
movs r2, #165
lsls r2, r2, #2
adds r1, r7, r2
str r3, [r1, #0]
movs r3, #167
lsls r3, r3, #2
adds r3, r7, r3
ldr r3, [r3, #0]
movs r5, r3
movs r3, #0
movs r6, r3
movs r3, r5
movs r1, #164
lsls r1, r1, #2
adds r0, r7, r1
str r3, [r0, #0]

push {r4, r5, r6, r7, lr} ;func()
sub sp, #20
add r7, sp, #0
ldr r0, [pc, #52]
str r0, [r7, #12]
ldr r0, [pc, #52]
str r0, [r7, #8]
ldr r0, [r7, #12]
movs r1, r0
movs r0, #0
movs r2, r0
ldr r0, [r7, #8]
movs r5, r0
asrs r0, r0, #31
movs r6, r0
movs r4, r5
movs r0, #0
movs r3, r0
movs r0, r1
orrs r0, r3
str r0, [r7, #0]
orrs r2, r4
str r2, [r7, #4]
ldr r3, [r7, #0]
ldr r4, [r7, #4]
movs r0, r3
movs r1, r4
mov sp, r7
add sp, #20
pop {r4, r5, r6, r7, pc}

Это для M0, но размер все равно впечатляет.

Добавлено after 11 minutes 25 seconds:
Reflector, строго говоря, у Вас возвращается объект класса std::pair, содержащий пару объектов класса void*, конструируемый и инициализируемый внутри вызываемой функции. Вообще классически, надо было тогда создать еще и класс наследник std::pair с нужным методом, а не функцию :)

Нет, std::pair без оптимизации привнес бы ощутимый оверхед, потому Pair был другой:
Код:
template<typename T1, typename T2 = T1>
struct Pair { T1 value1; T2 value2; };

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 18:10:03

Это для M0, но размер все равно впечатляет.

Что-ж - тогда буду так и использовать IAR, а не GCC :)
Раз уж вы про M0, то что говорит AEABI по поводу возврата unsigned long long из функций для M0?
Последний раз редактировалось jcxz Вт июн 04, 2019 18:14:32, всего редактировалось 1 раз.

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 18:11:06

Reflector, ну Вы же это не указали в первоначальном посте! Откуда мне было знать, что реализация была на структуре? А какой смысл тогда был говорить о C++, если, де факто, Вы пользовались только средствами C?

Re: Передать в функцию указатель, а получить указатель на ма

Вт июн 04, 2019 18:26:45

Reflector, ну Вы же это не указали в первоначальном посте! Откуда мне было знать, что реализация была на структуре? А какой смысл тогда был говорить о C++, если, де факто, Вы пользовались только средствами C?

ТС пишет на С, возможно стоило и пример со структурой привести на С, но я выбрал вариант на С++ который, тем не менее, от сишного отличается незначительно. Но там есть шаблоны, auto и структурное связывание, т.е. возвращаемый результат присваивается сразу паре переменных, а не структуре, как в оригинальном примере. И да, я же потом написал, что возвращается именно структура :)

Что-ж - тогда буду так и использовать IAR, а не GCC :)

На то он и -O0, с другой стороны для достаточно больших программ -O0 за счет запрета инлайнинга может давать размер меньше чем -O2, не говоря уже о -O3. И никто не заставляет этот -O0 использовать, многие сидят на -Og, хотя у него свои недостатки...

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 15:08:22

На то он и -O0, с другой стороны для достаточно больших программ -O0 за счет запрета инлайнинга может давать размер меньше чем -O2, не говоря уже о -O3. И никто не заставляет этот -O0 использовать, многие сидят на -Og, хотя у него свои недостатки...

Разговор вообще не об оптимизации шёл. А о том - можно ли возвращать два значения из функции одновременно? Мануал на IAR говорит, что он будет возвращать 64-битные значения в регистровой паре R0:R1 вне зависимости от уровня оптимизации. Так как такой стиль прописан в AEABI. И если хоть на каком-то уровне оптимизации это не выполняется - это означает несовместимость с AEABI.
Как видно из приведённого Вами листинга, GCC тоже возвращает u64 в регистровой паре R0:R1. Да - промежуточные вычисления он делает на стеке (при оптимизации -O0) и они какие-то очень громоздкие, но здесь речь не об оптимальности кода.

Вывод: Никаких проблем с возвратом двух указателей в виде u64 в R0:R1 не должно быть ни в IAR ни в GCC.

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 15:17:40

проблем-то, может, и не быть, но для чего так делать?!

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 16:15:33

Мануал на IAR говорит, что он будет возвращать 64-битные значения в регистровой паре R0:R1 вне зависимости от уровня оптимизации. Так как такой стиль прописан в AEABI. И если хоть на каком-то уровне оптимизации это не выполняется - это означает несовместимость с AEABI.

Зайди на сайт ARM и посмотри какие они компиляторы раздают... Для Cortex-A - eabi, для Cortex-M - none-eabi. Собственно таким arm-none-eabi gcc я свой пример и компилировал, потому что никакие линуксы и т.п. я на STM32 запускать не собираюсь :)

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 16:41:05

проблем-то, может, и не быть, но для чего так делать?!
А зачем так не делать? :))
Код получается намного меньше, не используется стек и пр. - плюсов много. Минусов - нет.

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 16:54:32

Достоинство ЯВУ только в том, что код получается более лёгким для восприятия.

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 17:01:20

ARV, а разве возврат функцией структуры так тяжел для восприятия?

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 18:22:05

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

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 18:25:16

ARV, Вы бы посмотрели внимательно на мой код (или код Reflector), прежде чем теории толкать...

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 18:27:25

Мне любопытно: насколько традиционный способ с возвратом через параметры окажется хуже, по сравнению с этим извратом?
<code> void get2param(char **ptr1, char **ptr2);</code>

Добавлено after 1 minute 32 seconds:
ARV, Вы бы посмотрели внимательно на мой код (или код Reflector), прежде чем теории толкать...

Я видел вариант с выделением старшего и младшего слов из long-a, это ваш вариант?
Структуру вроде даже не видел...

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 18:34:12

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

Добавлено after 1 minute 2 seconds:
Re: Передать в функцию указатель, а получить указатель на массив
ARV, у Вас глюки. Посмотрите внимательно на мой код

Re: Передать в функцию указатель, а получить указатель на ма

Ср июн 05, 2019 21:40:44

ARV, у Вас глюки. Посмотрите внимательно на мой код

Вариант с возвратом структуры приемлем вполне. Просто он был на предыдущей странице, а с мобильника неудобно просматривать много.
Мне не понравился вариант с упаковкой указателей в long.
Ответить