Встроенный ассемблер gcc получает ошибку lvalue, требуемую в инструкции asm

Мне нужно написать C-код, который делает

DDRB &= ~pins;

с встроенной сборкой (AVR). Я никогда не использовал его раньше. Моя попытка:

register uint8_t t1, t2; // temporary registers
__asm__ volatile (
    "in %[t1], %[w1_ddr]"   "\n\t"
    "mov %[t2], %[pins]"    "\n\t"
    "com %[t2]"             "\n\t"
    "and %[t1], %[t2]"      "\n\t"
    "out %[w1_ddr], %[t1]"  "\n\t"
    : [t1] "+r" (t1),
      [t2] "+r" (t2),
      [w1_ddr] "+I" (_SFR_IO_ADDR(DDRB))
    : [pins] "r" (pins)
);  

gcc выдает следующую ошибку lvalue required in asm statement. Что я делаю не так?


person Community    schedule 21.11.2012    source источник
comment
Зачем нужно писать на ассемблере? Что не так с DDRB &= ~pins;?   -  person Keith Thompson    schedule 22.11.2012
comment
@Keith: я использую его в критичном по времени коде, и я должен быть уверен в количестве тактов, которое тратит команда. С C я не могу быть уверен в этом.   -  person    schedule 22.11.2012


Ответы (1)


Ограничение «I» в AVR указывает, что операнд является константой. Значит не может быть "+", т.е. ввод-вывод. Сделайте это простым вводом, например:

register uint8_t t1, t2; // temporary registers
__asm__ volatile (
    "in %[t1], %[w1_ddr]"   "\n\t"
    "mov %[t2], %[pins]"    "\n\t"
    "com %[t2]"             "\n\t"
    "and %[t1], %[t2]"      "\n\t"
    "out %[w1_ddr], %[t1]"  "\n\t"
    : [t1] "+r" (t1),
      [t2] "+r" (t2)
    : [w1_ddr] "I" (_SFR_IO_ADDR(DDRB)),
      [pins] "r" (pins)
); 
person chill    schedule 21.11.2012
comment
Но я пишу в w1_ddr в последней строке. Я должен сказать, что w1_ddr является и входом, и выходом, не так ли? - person ; 22.11.2012
comment
О, простите, я идиот. w1_ddr на самом деле константа. Не могу удалить предыдущий комментарий. - person ; 22.11.2012