Вставка ассемблерного кода в скетч

Тема в разделе "Arduino & Shields", создана пользователем avt34, 22 июн 2017.

  1. avt34

    avt34 Нерд

    Приветствую!
    Есть ассемблерный код, который нужно выполнить в скетче. Но ни как не могу сообразить как правильно его перевести в формат, понимаемый компилятором.
    Вот что я пишу:
    Код (C++):
    byte CRCMaker(byte b_input,byte b_CRC)
    {
        asm volatile("mov %0,%%al"::"g"(b_input));
        asm volatile("mov %0,%%ah"::"g"(b_CRC));
        asm volatile("mov $8,%cx");
        asm volatile("mod1: rol $1,%al");
        asm volatile("rcl $1,%ah");
        asm volatile("jnc mod2");
        asm volatile("xor $0x69,%ah");
        asm volatile("mod2: dec %cx");
        asm volatile("jnz mod1");
        asm volatile("mov %%ah,%0":"=g"(b_CRC));
        return b_CRC;
    }
    А вот оригинал:
    Код (C++):

    BYTE CRCMaker(BYTE b_input, BYTE b_CRC)
    {
       __asm
       {
           mov al,b_input
           mov ah,b_CRC
           mov cx,8
       mod1:   rol al,1
           rcl ah,1
           jnc mod2
           xor ah,69h
       mod2:   dec cx
           jnz mod1
           mov b_CRC,ah
       }
       return b_CRC;
    }
     
    Подскажите, пожалуйста, в чём у меня ошибка? Как правильно вставить этот кусок ассемблера?
    Компилятор ругается на ассемблер:
    /tmp/ccrlEK72.s: Assembler messages:
    /tmp/ccrlEK72.s:988: Error: bad expression
    /tmp/ccrlEK72.s:988: Error: garbage at end of line
    /tmp/ccrlEK72.s:992: Error: constant value required
    /tmp/ccrlEK72.s:992: Error: bad expression
    /tmp/ccrlEK72.s:992: Error: garbage at end of line
    /tmp/ccrlEK72.s:996: Error: constant value required
    /tmp/ccrlEK72.s:996: Error: `,' required
    /tmp/ccrlEK72.s:996: Error: garbage at end of line
    /tmp/ccrlEK72.s:996: Error: junk at end of line, first unrecognized character is `8'
    /tmp/ccrlEK72.s:1000: Error: constant value required
    /tmp/ccrlEK72.s:1000: Error: junk at end of line, first unrecognized character is `1'
    /tmp/ccrlEK72.s:1004: Error: unknown opcode `rcl'
    /tmp/ccrlEK72.s:1004: Error: junk at end of line, first unrecognized character is `1'
    /tmp/ccrlEK72.s:1008: Error: unknown opcode `jnc'
    /tmp/ccrlEK72.s:1012: Error: unknown opcode `xor'
    /tmp/ccrlEK72.s:1012: Error: junk at end of line, first unrecognized character is `0'
    /tmp/ccrlEK72.s:1016: Error: bad expression
    /tmp/ccrlEK72.s:1016: Error: garbage at end of line
    /tmp/ccrlEK72.s:1020: Error: unknown opcode `jnz'
    /tmp/ccrlEK72.s:1024: Error: bad expression
    /tmp/ccrlEK72.s:1024: Error: `,' required
    /tmp/ccrlEK72.s:1024: Error: constant value required
    /tmp/ccrlEK72.s:1024: Error: garbage at end of line
     
  2. mcureenab

    mcureenab Гуру

    Это должен быть один вызов asm. Иначе смысла нет.
     
  3. mcureenab

    mcureenab Гуру

    arkadyf нравится это.
  4. mcureenab

    mcureenab Гуру

  5. avt34

    avt34 Нерд

    Спасибо за пример.
    Я делал так же по уже готовому примеру, возможно и даже наверняка, написал фигню.
     
  6. DetSimen

    DetSimen Guest

    мошт просто AVR не понимает x86 ассемблер? Поэтому и не выходит ничо?
     
  7. mcureenab

    mcureenab Гуру

    Это не для ATMega. Похоже не ассемблер для 80x86...
    Тебе CRC посчитать надо?
     
  8. avt34

    avt34 Нерд

    Да, вот так выглядит лучше:
    Код (C++):
    byte CRCMaker(byte b_input,byte b_CRC)
    {
        asm volatile
        (
         "mov %1, %%al\n\t"
         "mov %0, %%ah\n\t"
         "mov $8, %cx\n\t"
         "mod1: rol $1, %al\n\t"
         "rcl $1, %ah\n\t"
         "jnc mod2\n\t"
         "xor $0x69, %ah\n\t"
         "mod2: dec %cx\n\t"
         "jnz mod1\n\t"
         "mov %%ah,%0\n\t"
         :"=r"(b_CRC)
         :"r"(b_input)
         :
         );
        return b_CRC;
    }
    Но что значит вот эта ошибка?
    Код (C++):
    57: error: invalid 'asm': operand number missing after %-letter
          );
     
  9. avt34

    avt34 Нерд

    Да, да причём максимально аутентично, чтобы быть уверенным, что в CRC точно нет ошибки. Иначе бы я не стал ассемблер вставлять.
    Ассемблерный код взят из примера в документации к устройству.
     
  10. DetSimen

    DetSimen Guest

    а все равно это для х86
     
  11. avt34

    avt34 Нерд

    Вполне возможно. Я в ассемблере не силён. Как же это под ардуинку перевести?
     
  12. DetSimen

    DetSimen Guest

    в директории, где у тебя стоит Arduino IDE, по пути hardware\tools\avr\avr\include\util\ есть файл crc16.h
    тама всё написано. На название не смотри, там и crc8 есть
     
  13. avt34

    avt34 Нерд

    А это точно crc8?

    Код (C++):
    При формировании CRC используется примитивный неприводимый
    порождающий полином в 9-й степени P(X)-101101001b (169h). На пере-
    дающей стороне в конце массива используется нулевой байт (00h).
    Это из описания к протоколу.
     
  14. mcureenab

    mcureenab Гуру

    этого нет у AVR %%al и %%ah
     
    Igor68 нравится это.
  15. avt34

    avt34 Нерд

    А, я понял. Регистров таких нет?
     
  16. mcureenab

    mcureenab Гуру

    ни регистров ни %%.

    регистр называется просто r0, r1, r2, и т.д. некоторые регистры образуют пары для 16 битных операций.

    для r0 есть синоним __tmp_reg__. для r1 синоним __zero_reg__ Register r1, always zero.

    регистры для b_input и b_CRC компилятор сам распределит.

    для счётчика в цикле используйте __tmp_reg__.
     
  17. avt34

    avt34 Нерд

    Понял. Спасибо, буду разбираться.
     
  18. mcureenab

    mcureenab Гуру

    Эти строчки не нужны

    "mov %1, %%al\n\t"
    "mov %0, %%ah\n\t"
    ...
    "mov %%ah,%0\n\t"

    компилятор сам выберет в какие регистры положить b_CRC и b_input.

    в коде вместо al, ah ссылайтесь на %1, %0. %0 автоматически попадет в b_CRC.

    вместо cx можно использовать r20
    для константы 0x69 использовать r21
    и указать их после крайнего :

    :"r20 r21")

    чтобы компилятор знал какие регистры нужно восстановить после вызова asm.
    ... как то так
     
  19. avt34

    avt34 Нерд

    Благодарю.
     
  20. mcureenab

    mcureenab Гуру

    xor нету
    нужно заменить на

    ldi r21, 0x69

    ...

    eor %0, r21