Язык ассемблера ARMv7: как обратить массив символов и вывести его в другой массив символов

#c #assembly #arm #armv7

#c #сборка #arm #armv7

Вопрос:

Я новичок в программировании на языке ассемблера ARM7.

Я пытаюсь реализовать простую функцию в ARM assembly, которая принимает массив символов, переворачивает его и сохраняет в другой массив символов равной длины.

Ниже я включил как свой код на C, так и код на языке ассемблера ARM7. Однако мой код не выводит правильную перевернутую строку; что, вероятно, связано с моими инструкциями ASM. Я использую Linux на 32-разрядной машине.

reverseString.s (код ниже)

 .global reverseString

.text

reverseString:
    MOV R2, R1          @store strIn[0] into R2
    PUSH {R4-R6}        @save regs
    MOV R4, #0          @R4 will be strIn_len reg, store 0 for count

@finds the length of the strIn arr
strlen_loop:
    LDR R3, [R2], #1    @increment through strIn arr
    ADD R4, R4, #1      @count the no. of chars
    CMP R3, #0          @check if null term hit
    BNE strlen_loop     @if yes leave, else cont.

@string reversal loop
    MOV R0, R2          @movs ptr of strOut to last element
loop:
    CMP R4, #0          @makes sure count !=0
    BEQ loop_end        @if yes, end loop
    LDR R5, [R1], #1    @incr. address of strIn in R1 and put into R5
    STR R5, [R0], #-1   @store the value at address in strOut
    SUB R4, R4, #1      @decrement counter var
    B loop

loop_end:
    POP {R4-R6} @restore regs
    BX LR
  

reverseString.c (код ниже)

 #include <stdio.h>
#include <stdint.h>

extern void reverseString(char strOut[], const char strIn[]);

#define COUNT 6

int main()
{ 
  const char strIn[COUNT] = "candy";
  char strOut[COUNT];
  reverseString(strOut, strIn);
  printf("%srn", strOut);
  return 0;
}
  

скомпилирован в командной строке с использованием

 gcc -g -o reverseString reverseString.s reverseString.c
./reverseString
  

вывод

Комментарии:

1. Какой результат вы получаете? Вы прошли через это в отладчике? Почему strIn значение const, когда вы собираетесь его изменить?

2. Спасибо за вашу помощь. Я использовал отладчик и пошагово проверил весь код. После проверки регистров они уменьшаются и инкрементируются должным образом. Кажется, что в регистре может быть мусор, как только я получу к нему доступ. Поскольку мой вывод выглядит как приведенный выше мусор. Также strIn предполагается, что он не изменился. Я просто хочу получить доступ к элементам (не изменять их значения).

3. Вы можете передать указатель src как const , но вы не можете объявить исходный массив как const, если собираетесь изменять его с помощью scanf. Возможно, вам будет полезно поиграть с некоторым кодом C, скомпилированным для ARM. Это может помочь разработать логику на потенциально более знакомом языке. godbolt.org/z/e1uq_Q Поскольку вы копируете по 1 байту за раз, вам может потребоваться использовать эти конкретные инструкции.

4. Да, вы правы. Это была оплошность с моей стороны, и ее не следует объявлять как const, если я собираюсь использовать scanf. Я исправлю это и сделаю его постоянным. Также, спасибо за ссылку на этот веб-сайт, это очень полезно.

5. Вы пытаетесь использовать ARM7 или ARMv7?

Ответ №1:

Попробуйте провести эксперимент. Инициализируйте strOut что-нибудь, а после вызова reverseString выведите оба strIn и strOut . Обратите внимание на несколько забавный результат.

Теперь, в

         MOV R0, R2          @movs ptr of strOut to last element
  

Последний элемент чего именно?

R2 в strlen_loop приведенном выше примере пройден strIn , и в этой точке содержится адрес его конца. Теперь R0 также содержит этот адрес, а остальной код не имеет к strOut никакого отношения. Он пытается выполнить обратное strIn .

Этот шаг не только вреден, но и избыточен. Просто скопируйте из [R2], #-1 в [R0], #1 .

Комментарии:

1. Спасибо, что уделили мне время. Когда вы говорите копировать из [R2], #-1 в R0], #1 , какая это строка? Это STR R5, [R0], #-1 ?