Inline ASM — используйте переменную c 16 или 32 битов (рукоятку GCC, режим большого пальца руки)

В настоящее время я использую следующий встроенный ASM для Cortex-M3 для ветвления к определенному адресу во flash.

__asm("LDR R0, =0x8000"); //  Load the branch address
__asm("LDR R1, [R0]");    //  Get the branch address
__asm("ORR R1, #1");      //  Make sure the Thumb State bit is set.
__asm("BX R1");           //  Branch execution
  • Однако я хочу заменить жестко закодированное значение 0x8014переменной C, которая будет вычисляться на основе некоторых других условий.
  • Максимально возможное значение этой переменной-0x20000, поэтому я планировал использовать a uint32_tдля ее хранения.
  • Используется компилятор arm-none-eabi-gccv4.9.3

Я попытался изменить мой встроенный ASM следующим образом:

uint32_t destination_address = 0x8000;
__asm( "LDR R0, =%[dest]" : : [dest]"r"(destination_address) );

Однако это создает ошибку компилятора:

undefined reference to `r3'

Я довольно новый для inline ASM в целом. Я пытался исследовать эту проблему в течение двух дней или около того, но меня смутили противоречивые ответы из-за разнообразия компиляторов и того факта, что я использую инструкции большого пальца для Cortex-M3.

Я думаю, что моя проблема заключается в том, что мне нужно найти правильное ограничение для переменной destination_address(диапазон 0x0 — 0x20000), но я не уверен.

1 ответ

  1. почему вы используете встроенную сборку?

    extern void HOP ( unsigned int );
    ...
    unsigned int some_address;
    ..
    some_address = some_math;
    HOP(some_address);
    

    и несколько строк реального asm, которые вы можете использовать компилятор c, если вы действительно чувствуете, что вы должны сделать объект из, Чтобы связать.

    .globl HOP
    HOP:
       bx r0
    

    добавленное преимущество это ветвь ссылка в основном, если вы хотите быть.

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

    еще одна вещь, которую вы можете сделать, если у вас есть это

    unsigned int some_address;
    ..
    some_address = some_math;
    

    эту сборку можно использовать где-то в проекте.

    ldr r0,=some_address;
    ldr r0,[r0]
    bx r0
    

    и компоновщик разрешит адрес переменной C. поэтому можно использовать реальный ассемблер или встроенный для чего-то подобного. (если встроенный не поддерживает что-то вроде mov %0, some_address; bx %0 и делает работу за вас)