Как добавить два сборочных массива в arduino

Эй, ребята, то, что я пытаюсь сделать, это суммировать два массива и возвращать новый массив; например, если дано

  uint8_t a[] = {2, 4, 6};
  uint8_t b[] = {1, 2, 3};

Я должен получить {3, 6, 9} То, что я пытаюсь сделать, это вызвать файл .ino для файла сборки, который будет делать это в сборке, а не в C, и это то, что у меня сейчас есть в сборке:

// mimics void sumArrays(uint8_t *a, uint8_t *b, uint8_t *c, byte length){} method
    .global sumArrays
    sumArrays:
      //r18 is the byte length
      //r24 and r25 first  array 31,30
      //r23 and r22 second array 29,28
      //r21 and r20 third  array 27,26

      mov r30, r24
      mov r31, r25
      mov r28, r22
      mov r29, r23
      mov r26, r20
      mov r27, r21
      ldi r17, 0 //counter variable
      ldi r19, 1
      call printRegs
      //jmp sumLoop

      ret

    sumLoop:
      cp r17, r18
      brge endSumLoop
      ldi r16, 0
      add r16, Z+
      add r16, Y+
      st X+, r16
      add r17, r23
      jmp sumLoop:
    
    endSumLoop: 
      ret

Однако я получаю sketch/assignment13.S:65: Error: требуется постоянное значение, которое, скорее всего, связано с

add r16, Z+
add r16, Y+

Линии, но в противном случае, как бы я добавил его во временную переменную при перемещении указателя?

, 👍1

Обсуждение

Почему вы используете assembly для этого вместо C?, @Gabriel Staples


1 ответ


Лучший ответ:

2
add r16, Z+

Вы, вероятно, имели в виду что-то вроде

add r16, memory[Z+]

Однако AVR - это RISC-процессор. У него есть инструкции для обращения к памяти и инструкции для выполнения арифметики, но у него нет “сложных” инструкций, которые одновременно адресуют память и выполняют арифметику с адресованными данными. Поэтому вы должны использовать отдельные инструкции, чтобы:

  1. Загрузка (ld) данных из оперативной памяти

  2. займись арифметикой

  3. хранить (st) результат в оперативной памяти

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

  1. Если вы смешиваете ассемблер и C / C ++, вам следует обратить внимание на соглашения ABI. В частности, некоторые регистры, такие как r28 и r29, “принадлежат” вызывающему абоненту. Если вашей функции нужно их использовать, она должна сохранить их содержимое (обычно помещаяего в стек), прежде чем забивать их, и восстановить их (pop) перед возвращением.

  2. Для сложения двух 8-битных чисел (a + b) достаточно одного сложения. Нет смысла начинать сложение с нуля (т. е. вычислять 0 + a + b).

  3. Для управления счетчиком может быть удобнее уменьшить начальный счетчик, который вы задали (как в C: if (--length) return;) вместо того, чтобы использовать дополнительную переменную, которая увеличивается.

  4. Нет необходимости разбивать такую простую функцию на более мелкие функции.

,