2016-04-15 2 views
1

Как сказано в названии, моя цель - написать программу в C и ARM, которая декодирует строку, сдвигая значение байта каждого символа на определенную сумму. Символ «пробел» не сдвигается, а просто копируется в результирующую строку. Процесс заканчивается, когда нулевой ограничитель находится.Caeser decoder in ARM Assembly

Вот мой C код:

#include <stdio.h> 

extern void init(char * encrypt); 
extern char * decrypt(char * encrypt, int shift); 

int main(int argc, char * argv[]) 
{ 
    char * result; 
    char encrypt[] = "GSRKVEXYPEXMSRW CSY LEZI JSYRH XLI WLMJX ZEPYI"; 
    int i; 

    init(encrypt); 
    for (i = 1; i < 5; i++) { 
     result = decrypt(encrypt, i); 
     printf("Possible decrypt with shift %d: %s\n", i, result); 
    } 
} 

Вот мой ARM код (все это в один файл с именем decrypt.s):

@ init: reserves space for the decryption 
    .global init 
    .text 
init: stmfd sp!, {v1-v6, lr} 
    mov v1, a1 
    bl strlen 
    bl malloc 
    bufferAddr: .fill 4, 1, 0 
    str a1, bufferAddr 
    @mov a2, v1 
    @bl strcpy 

    ldmfd sp!, {v1-v6, pc} 

@ decrypt: performs shifting of letters to decrypt string 
    .global decrypt 
    .text 
decrypt: stmfd sp!, {v1-v6, lr} 
    mov v1, a1 @ v1 is the pointer to encrypt (string) 
    ldr v2, =bufferAddr @ v2 is the pointer to result (string) 

    loop: 
     ldrb v3, [v1], #1 @ v3 is the current char (8-bit number) 

     cmp v3, #0 
     streqb v3, [v2], #1 
     beq endLabel 

     cmp v3, #32 @ check if v3 == "space" 
     streqb v3, [v2], #1 @ if true, store space in result, increment 
     beq loop @ if true, proceed to next char 

     sub v3, v3, a2 @ shift v3 by shift-value 
     cmp v3, #65 @ check if v3 >= 65 (A) 
     strgeb v3, [v2], #1 @ if true, store char in result, increment 
     bge loop 

     @ if less than A 
     add v3, v3, #26 @ add 26, wrap between A-Z 
     strb v3, [v2], #1 @ if true, store char in result, increment 
     b loop 
    endLabel: 

    ldr a1, =bufferAddr 

    ldmfd sp!, {v1-v6, pc} 
.end 

Проблема заключается в том, что идет только через цикл один раз, затем он застревает. Иногда он печатает ошибку в строках «sim: unknown SWI ...» или «unknown v6 isbn ...». Или, что хуже всего, он просто ничего не печатает (бесконечный цикл?)

Я не уверен, в чем проблема, моя логика, похоже, имеет смысл. я прочитал следующие байты:

  • Если это нуль-терминатор, я положил его в результирующей строке, а также, и в конце цикла.
  • Если это пространство, я помещаю пространство в результирующую строку и продолжаю цикл.
  • Если это> = 65 (что ДОЛЖНО быть, если только Space/null-terminator), я вычитаю значение сдвига. Если результирующее значение> = 65, я помещаю его в результирующую строку. Если это < 65, я добавляю 26, а затем помещаю его в результирующую строку, поэтому успешно переношу на заглавные буквы алфавита.
  • Существует (должен быть) нет другого случая.

Однако я все еще получаю ошибки или, возможно, бесконечный цикл. Есть идеи?

+0

Кроме того, как я могу гарантировать, что одна «функция/метка» не попадает в другую? После вызова ldmfd автоматически ли он возвращается в предыдущее местоположение функции? – Dave

+1

Лучшая идея - это всегда: один шаг через код сборки в отладчике. Еще один трюк заключается в том, чтобы создать код, а затем разобрать его снова, чтобы увидеть, действительно ли он выглядит так, как предполагалось. Для начала рассмотрим вызов 'bl malloc' в' init' - когда это вернется, что, по вашему мнению, произойдет дальше? – Notlikethat

+0

Нет, он не возвращается. Как он это знает? Вам нужно сказать, чтобы он вернулся. Также он не «падает» на другой ярлык. Этикетки - это всего лишь этикетки. Это не более чем номера строк или места памяти. –

ответ

3

str a1, bufferAddr сохраняет значение из регистра в ячейке памяти, на которую указывает bufferAddr. Поскольку это находится в середине функции init, она работает только в первый раз.

Однако ldr v2, =bufferAddr загружает значение bufferAddr, что приводит к результату перезаписи decrypt.

Вы должны использовать ldr v2, bufferAddr.

+0

После исправления хранения bufferAddr у меня все еще были ошибки. Я избавился от знака равенства перед буферомAddr, и все просто сработало. Спасибо всем! – Dave