микс c и сборка cortex-m0 - PullRequest
1 голос
/ 07 мая 2020

Я хочу написать процедуру для cortex-m0 в G CC C, где смешайте C и ассемблерный код. Я пробую что-то вроде этого

__attribute__((naked)) uint8_t dummy(uint8_t value)
{
    asm volatile (
            "push   {r1-r7, lr}\n\t"
             // R0 contains input value
             //here i do some operation on registers r0..r7         
             //.....
             //I guess result will be in the R0 register
            "MOV R0, R3\n\t"

            "pop    {r1-r7, pc}\n\t"
        );
}

, но, к сожалению, у меня проблемы:

  • из-за этого моя программа вылетает.
  • компилятор утверждает, что моя «фиктивная» процедура не имеет возвращаемого значения

РЕДАКТИРОВАТЬ, РАБОЧИЙ КОД: Я переместил код в отдельный файл .s, и окончательное решение выглядит следующим образом

    .syntax unified
    .arch armv6-m
    .text
    .thumb
    .thumb_func
    .align 1
    .globl    dummymethod
    .type    dummymethod, %function
dummymethod:
    .fnstart
            PUSH    {r1-r7, lr}
            // here some operation on registers R0..R7

            MOV R0, R3 //result is in R0

            pop {r1-r7, pc}

    .pool
    .cantunwind
    .fnend
    .size   dummymethod,.-dummymethod

Ответы [ 2 ]

2 голосов
/ 07 мая 2020

использовать реальную сборку

.cpu cortex-m4
.thumb
.globl dummy
.thumb_func
dummy:
    mov r0,r3
    bx lr

соглашение о вызовах позволяет изменять r0-r3, возврат в r0, вы не трогаете r4, r5, r6, r7, lr, поэтому нет необходимости pu sh те.

некрасиво, но вы можете собрать его с помощью g cc, gnu ассемблер, as, предпочтительнее (arm-something-as)

1 голос
/ 08 мая 2020

Падение конца функции naked на самом деле не является ошибкой. Предупреждение в этом случае было ошибкой G CC, которая была исправлена ​​где-то до G CC 5.4. (Но code-gen тот же; более старые версии G CC, которые предупреждают, не нарушают ваш код.)

Написание функции naked в C + дает лишь несколько незначительных преимуществ. asm:

  • Если у вас есть код, который может компилироваться для любого режима, компилятор выдает директивы thumb vs. ARM. (Cortex-M0 предназначен только для большого пальца, поэтому в вашем случае никакой пользы.)
  • информация об отладке, динамический c размер библиотечной функции и другие подобные метаданные.
  • заставьте компилятор измените имя C ++ вместо того, чтобы объявлять его extern "C", если вы писали C ++.
  • Вы можете поддерживать его рядом с некоторым фактическим кодом C, с которым он взаимодействует.

В противном случае вы могли бы просто написать отдельный файл asm. Он все еще не может быть встроен, как не naked функция-оболочка вокруг GNU C Extended asm-оператора.

Я не эксперт по ARM, но в этом нет ничего плохого вы использовали встроенную функцию asm / naked. Тело naked в основном является единственным разумным вариантом использования для GNU C "Basi c" asm (без ограничений).

Если вы скомпилируете это с правильными параметрами G CC, G CC должен выдать те же директивы, которые вы использовали в резервном asm. (Хотя не .cantunwind в случае, если это имеет значение.)


Из Godbolt , gcc5.4.1 -O2 -Wall -mcpu=cortex-m0 -mthumb -fverbose-asm компилирует его чисто (без предупреждений). Это вывод asm с неотфильтрованными директивами, но некоторое ручное редактирование для удаления директив и меток, я думаю, просто беспорядок (включая информацию об отладке):

        .syntax unified
        .cpu cortex-m0
        .fpu softvfp

        .text
        .global dummy
        .code   16
        .thumb_func
        .type   dummy, %function
dummy:
        .syntax divided
        push   {r1-r7, lr}
        MOV R0, R3
        pop    {r1-r7, pc}

        .thumb
        .syntax unified
        .cfi_endproc
        .size   dummy, .-dummy

Поскольку вы используете процессор только для большого пальца, вы не требуется взаимодействие большого пальца через bx lr, но, как указывает таймер @old: если вы можете оставить LR нетронутым во время выполнения функции, вы можете просто вернуться с bx lr вместо того, чтобы вставлять его обратно в P C.

Также обратите внимание, что первый аргумент передается в R0, поэтому чтение R3 означает чтение регистра, который, по утверждению вашего прототипа, не является входом.


Перемещение это в автономный файл asm совершенно нормально, так же верно и, вероятно, лучший выбор. Но поскольку вы спросили, как это сделать с помощью функции naked, это тоже должно работать.

...