Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: avr-libc inline assembler
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
fritsu
Помогите разобраться. Мне нужно сделать из такого ассемблерного кода:
Код
ldi temp,8
in_1:
sbic PinB,data_in
jmp in_2

sec
jmp in_3

in_2:
clc
in_3:
rol in1

cbi  PORTB,CLK
sbi  PORTB,CLK
dec temp
brne in_1
sts _in1,in1


inline вставку . in1, temp - регистры .
В целом много чего непонятного. Например output и input параметры нужно заполнять для каждой команды или не для каждой?
Также не понятно для чего нужны модификаторы. Например есть параметр
Код
"=r" (value)
про value понятно внешняя переменная, а что такое "=r" непонятно.
кто, что, подскажет?
Сергей Борщ
QUOTE (fritsu @ May 3 2011, 09:29) *
Например output и input параметры нужно заполнять для каждой команды или не для каждой?
Если вы каждую ассемблерную команду оформляете как отдельную асм-вставку - то нужно для каждой. Но это не имеет особого смысла. Вам надо весь этот блок оформить как единую вставку и уже для всего этого блока описать параметры.
QUOTE (fritsu @ May 3 2011, 09:29) *
Также не понятно для чего нужны модификаторы. Например есть параметр
CODE
"=r" (value)
про value понятно внешняя переменная, а что такое "=r" непонятно.
Ими вы сообщаете компилятору, какие переменные/константы программы компилятор должен загрузить в регистры или выгрузить (включая тип этих переменных), а также какие регистры или память портит ваша вставка, чтобы компилятор мог учесть это при генерации остального кода.
В частности, =r означает, что под переменную компилятор должен выделить в любой регистр и после вставки забрать значение из этого регистра (ваша асм-вставка производит запись в эту переменную). =r означает, что ваша вставка и читает из этой переменной и пишет в нее, т.е. компилятор должен еще и загрузить значение переменной в выделенный регистр перед вставкой (аналогичного эффекта можно достигнуть указав =r в output constraint и r для этого же параметра в input constraint)

Ваша вставка будет выглядеть примерно так:

CODE
#include  <stdint.h>

__attribute__((__always_inline__))
inline uint8_t read_port()
{
    uint8_t Counter = 8;
    uint8_t Result;

    asm volatile(
    "1:                             \r\n"
    "   SEC                         \r\n"
    "   SBIC    %2, %3              \r\n"
    "   CLI                         \r\n"
    "   ROL     %0                  \r\n"
    "   DEC     %1                  \r\n"
    "   BRNE    1b                  \r\n"
    :"=r"(Result),"+r"(Counter)
    :"I"(_SFR_IO_ADDR(PINB)), "I"(data_in)
    );
    return Result;
}
Я немного сократил ее...
Обратите внимание, что Counter объявлен как +r, ибо эта вставка его портит.

Можно красивее:
CODE
__attribute__((__always_inline__)) inline uint8_t read_port()
{
    uint8_t Counter = 8;
    uint8_t Result;

    asm volatile(
    "1:                       \r\n"
    "   SEC                   \r\n"
    "   SBIC %[port], %[pin]  \r\n"
    "   CLI                   \r\n"
    "   ROL  %[Result]        \r\n"
    "   DEC  %[Counter]       \r\n"
    "   BRNE 1b               \r\n"
    :[Result]"=r"(Result),[Counter]"+r"(Counter)
    :[port]"I"(_SFR_IO_ADDR(PINB)), [pin]"I"(data_in)
    );
    return Result;
}


Вообще, ответы на основные свои вопросы вы найдете в документации на avr-libc в файле doc/avr-libc/avr-libc-user-manual/inline_asm.html
fritsu
Цитата(Сергей Борщ @ May 3 2011, 11:23) *
Обратите внимание, что Counter объявлен как +r, ибо эта вставка его портит.

т.е. "+" -это то что портим, а "r" то что переменную грузим в регистр? я правильно понял?

Цитата(Сергей Борщ @ May 3 2011, 11:23) *
Код
:[port]"I"(_SFR_IO_ADDR(PINB)), [pin]"I"(data_in)

data_in это номер бита(по сути константа), каким образом это значение передать во вставку и почему ты воспользовался модификатором "I"

Цитата(Сергей Борщ @ May 3 2011, 11:23) *
Вообще, ответы на основные свои вопросы вы найдете в документации на avr-libc в файле doc/avr-libc/avr-libc-user-manual/inline_asm.html

Честно говоря больше появилось вопросов чем ответов, после чтения этого мана.
Сергей Борщ
QUOTE (fritsu @ May 4 2011, 09:25) *
т.е. "+" -это то что портим, а "r" то что переменную грузим в регистр? я правильно понял?
"+" - это "и пишем и читаем". "=" - "пишем"
QUOTE (fritsu @ May 4 2011, 09:25) *
data_in это номер бита(по сути константа), каким образом это значение передать во вставку и почему ты воспользовался модификатором "I"
Каким образом передать - я показал в примере кода. I - потому что это целочисленная константа, а поскольку это номер бита, она не будет больше 63.
fritsu
Цитата(Сергей Борщ @ May 5 2011, 17:00) *
Каким образом передать - я показал в примере кода.


т.е. как-то так?:
Код
    uint8_t data_in = 6;
    asm volatile(
....
        : "I"(data_in)
....
}


Просто я думал если это константа, нет смысла объявлять переменную. Когда я указывал на прямую в ассемблерной вставке, выдавалась ошибка.

А так, благодарю за пример, все стало гораздо понятнее.
Сергей Борщ
QUOTE (fritsu @ May 6 2011, 12:59) *
т.е. как-то так?:
CODE
    uint8_t data_in = 6;
    asm volatile(
....
        : "I"(data_in)
....
}
Если это С, то #define data_in 6
Если C++, то можно uint8_t const data_in = 6;
В С может прокатить static uint8_t const data_in = 6; но без гарантий.
fritsu
Цитата(Сергей Борщ @ May 6 2011, 17:29) *
Если это С, то #define data_in 6
Если C++, то можно uint8_t const data_in = 6;

Все, спасибо. Дух ассемблерных вставок, более-менее для меня стал понятен.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.