Неравноправие регистров общего назначения

Тема в разделе "Микроконтроллеры AVR", создана пользователем a1000, 15 окт 2019.

  1. a1000

    a1000 Гуру

    В микроконтроллерах AVR семейства Mega имеется 32 регистра общего назначения. (Не буду утверждать о всём семействе, но в ATmega8 и ATmega328 точно.) Так вот, старшие регистры (R16-R31) используются без всяких ограничений, а вот с регистрами R0-R15 не всё так просто. Как писал в интернете один товарищ - "они какие-то ущербные". Как пример - не поддерживают прямую запись константы инструкцией LDI.
    Попытка найти подробную информацию по данному вопросу не дала необходимых результатов. В даташите информации об этом нет совсем (возможно плохо искал, если так, то ткните носом в номер страницы). На просторах интернета только отрывочные сведения. Где можно об этом почитать подробно?
     
  2. asam

    asam Гик

    Открываем http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-0856-AVR-Instruction-Set-Manual.pdf и смотрим какие команды с R16-R31 работают, а с R1-R15 нет. Поиск по 16 ≤ d ≤ 31 в помощь.

    Я двенадцать таких комманд нашел
    Код (Text):

    ANDI – Logical AND with Immediate
    CBR  – Clear Bits in Register
    CPI  – Compare with Immediate
    LDI  – Load Immediate
    LDS (16-bit) – Load Direct from Data Space
    MULS – Multiply Signed
    ORI  – Logical OR with Immediate
    SBCI – Subtract Immediate with Carry SBI – Set Bit in I/O Register
    SBR  – Set Bits in Register
    SER  – Set all Bits in Register
    SUBI – Subtract Immediate
    STS (16-bit) – Store Direct to Data Space
     
    Плюс 4 которые работают только с R16- R23
    Код (Text):

    FMUL   – Fractional Multiply Unsigned
    FMULS  – Fractional Multiply Signed
    FMULSU – Fractional Multiply Signed with Unsigned
    MULSU  – Multiply Signed with Unsigned
     
     
    Последнее редактирование: 15 окт 2019
    a1000, DetSimen, Daniil и ещё 1-му нравится это.
  3. a1000

    a1000 Гуру

    Спасибо, буду читать.
    Ещё в инете упоминалось об особом статусе регистров R0 и R1. Кто может об этом что-нибудь рассказать.
     
  4. parovoZZ

    parovoZZ Гуру

    вот это шляпа
    и вот эти кепки
    эмулируются на тех ядрах, где нет аппаратного умножителя)
    На новых аттинях с аппаратным умножителем на выполнение этих команд уходит 2-4 такта (специально проверял внутрисхемным отладчиком))).
     
  5. asam

    asam Гик

    Во многих операциях они выполняют роль 16 битного аккумулятора. А вообще, читайте http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-0856-AVR-Instruction-Set-Manual.pdf там все написано.
     
    Igor68 нравится это.
  6. SergeiL

    SergeiL Оракул Модератор

    Тут вопрос философский.
    А зачем Асм? Люди старались, сильно адаптировали компилятор Си, причем с оптимизацией...
    Си очень оптимально компилируется.
    Вы пробовали написать код на Си и скомпилировать. Потом посмотреть что получилось?
    Я просто писал и на Асме и на Си. Сейчас Асм не нужен, только для познающих мир.
    Что нельзя сделать на Си, что можно на Асме?
     
  7. Igor68

    Igor68 Гуру

    snapshot62.png
    Случилось переделывал "прошивку" Commotion driver for 4 motors. Были исходники, гле было умножение на 256, где был очевидный сдвиг влево на 8 бит. А оказывается сдвигов было 8, т.е надо было прочитать 8 инструкций сдвига и их выполнить - не считая самого выполнения ещё и 8 обращений к коду. А тут два такта на выполнение и только 3 байта на выполнение прочитать процессору. А что быстрее?

    И явно, что регистры R0 и R1(регистровая пара) двухбайтный аккумулятор. В I8080 регистр А так же аккумулятор. Имя регистра А это с нулевым номером.
     
  8. Igor68

    Igor68 Гуру

    А если возьмёте ARM/Cortex, то увидите что на ассемблере там есть ещё указывается регистр результата. А в других схемах (ядрах) применяется аккумулятор как таковой для сохранения результата. А вот слово состояния (тут указываются биты нулевого результата и бита переноса) результата отображаемые в регистре статуса. Именно по этим битам и происходит условное ветвление программы - анализ результата после выполнения.
     
  9. Igor68

    Igor68 Гуру

    Особенно интересно вызывать некую функцию. В одном случае надо сохранить регистры в стеке, а в другом выполнять операции в свободных регистрах... ну и перетаскивать параметры между регистрами. Это экономит время обращения к памяти. К примеру если в функции умножение, то результат будет в аккумуляторе и надо беспокоиться только о содержимом аккумулятора и регистра статуса. Но их реально таскать по регистрам совсем не обращаясь к стеку. При вызове функции Си как правило происходит резервирование регистров которые будут применяться в ней в стеке и при возврате из стека восстановление их содержимого. Можно конечно сделать и оптимизацию компилятором, го не всегда это реально.
    Самый быстрый код реально сделать только на ассембллере, Хоть Си и крут и максимально приближен по оптимальности. Вот только ассемблер малопонятен в понимании и к нему надо привыкнуть. Да и для каждого процессора свой ассемблер. А надо ещё и представлять архитектуру машины. А Си на разных архитектурах один и знать такого особого(архитектурного, процессорного) ничего не надо, хоть и желательно.
     
    DetSimen нравится это.
  10. DetSimen

    DetSimen Guest

    Надо. Для любых программ, чуть сложнее, чем blink. Для авнакода - не надо, и так сайдёть.
     
  11. parovoZZ

    parovoZZ Гуру

    @Igor68 имел ввиду CPU со всеми его регистрами, а не периферию.

    зато на сях код пишется быстрее.
     
    Igor68 нравится это.
  12. Igor68

    Igor68 Гуру

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

    К примеру: А кого колышет указатель стека или счётчик команд в программе на Си? Или регистр статуса. А по поводу блинка - есть её вариант демонстрации RTX.
     
  13. Igor68

    Igor68 Гуру

    По поводу вызова подпрограмм в Keil помница описание функций - первый входной параметр R0, второй R2 и т.д. Ну и возвращаемое значение было упомянуто.
     
  14. a1000

    a1000 Гуру

    Приведу высказывание уважаемого DI HALT о его отношении к Ассемблеру
    "Почему люблю? Ну дык, если Си это тупое ремесло, быстро и результативно, то Ассемблер это филигранное искусство. Как маньяки вроде Jim‘a из бумаги и только из бумаги [1] клепают шедевры, хотя, казалось бы, купи готовую сборную модель и клей себе в удовольствие. Так и тут — от самого процесса прет нипадецки. В том числе и от затраха с отладкой :))))"
    И ещё
    "Разумеется ни о какой типизации переменных, начальной инициализации, контроля за переполнениями и прочих буржуазных радостей говорить не приходится. Это Спарта! В смысле, ассемблер. Все ручками.
    Если провести аналогию с Си, то это как работа с памятью через одни лишь void указатели. Сишники поймут. Поймут и ужаснутся. Т.к. мир этот жесток и коварен."
     
  15. DetSimen

    DetSimen Guest

    Тока в Си изначально не было void указателей. Вот незадача. :)
     
  16. Igor68

    Igor68 Гуру

    Код (C++):
    uint8_t buf[4];
    ...
    (*(uint16_t*)(&buf[0])) = 0xa55A;
    ....
    (*(uint32_t*)(&buf[0])) = 0xF0F0F0F0;
    ....
    (*(float*)(&buf[0])) = 3.14;
    ...
     
    Наверное я то-то не понял для Си? С точки зрения других языков (не Си) не встречал такого удобства. Да и кроме Си ничего не знаю. Си впрочем не знаю, но использую. Русский язык то же не знаю, но пользуюсь.
    Ассемблер ограничен возможностью только самого ядра и ничем более.
     
  17. parovoZZ

    parovoZZ Гуру

    Неа)) Вышеприведенные команды *MUL* тому подтверждение)
     
  18. SergeiL

    SergeiL Оракул Модератор

    А как без
    Код (C++):
    void  *ptr;
    С самого начала - не знаю, но уже 88-ом были и использовались.
    Вот пример из настоящего:
    Код (C++):
    typedef struct _mqtt_publish_struct
    {
      const char  *Mqtt_Pub_String;
      void        (*function) (const char * topic, void  *val,uint8_t numb);
      void        *val;
      uint8_t     numb;
    } MQTT_Publish_Struct;
     
     
  19. Igor68

    Igor68 Гуру

    В приведённом MUL выполняется ядром... верно и не все процессоры умеют MUL. А I8080(КР850ВМ80А) к примеру и SUB не умеет. Так что только ядром.
    Простите ошибся SUB I8080 умеет - это я с PIC16F84 спутал.
     
    Последнее редактирование: 19 окт 2019
  20. SergeiL

    SergeiL Оракул Модератор

    А чем плох:
    Код (C++):
    void  *ptr;
    Чем он отличается, например от
    Код (C++):
    double *ptr;
    Чем?