Как сказано в названии, моя цель - написать программу в 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, а затем помещаю его в результирующую строку, поэтому успешно переношу на заглавные буквы алфавита.
- Существует (должен быть) нет другого случая.
Однако я все еще получаю ошибки или, возможно, бесконечный цикл. Есть идеи?
Кроме того, как я могу гарантировать, что одна «функция/метка» не попадает в другую? После вызова ldmfd автоматически ли он возвращается в предыдущее местоположение функции? – Dave
Лучшая идея - это всегда: один шаг через код сборки в отладчике. Еще один трюк заключается в том, чтобы создать код, а затем разобрать его снова, чтобы увидеть, действительно ли он выглядит так, как предполагалось. Для начала рассмотрим вызов 'bl malloc' в' init' - когда это вернется, что, по вашему мнению, произойдет дальше? – Notlikethat
Нет, он не возвращается. Как он это знает? Вам нужно сказать, чтобы он вернулся. Также он не «падает» на другой ярлык. Этикетки - это всего лишь этикетки. Это не более чем номера строк или места памяти. –