简体   繁体   中英

Caesar decoder in ARM Assembly

As it said in the title, my objective is to write a program in C and ARM assembly that decodes a string by shifting the byte value of each character by a certain amount. The "space" character isn't shifted, instead just copied over to the resulting string. The process ends when the null-terminator is located.

Here is my C code:

#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);
    }
}

Here is my ARM code (this is all in one file called 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

The problem is, it only goes through the loop once, then it gets stuck. Sometimes it prints an error along the lines of "sim: unknown SWI..." or "unknown v6 isbn...". Or worst of all, it just prints nothing (infinite loop?)

I'm not sure what the problem is, my logic seems to make sense. I read the next byte:

  • If it's null-terminator, I put it in the resulting string as well, and end the loop.
  • If it's space, I put the space in the resulting string, and continue the loop.
  • If it's >= 65 (which it SHOULD be, unless Space/null-terminator), I subtract the shift-value. If the resulting value is >= 65, I put it in the resulting string. If it's < 65, I add 26, then put it in the resulting string, therefore successfully wrapping to the capital letters of the alphabet.
  • There is (should be) no other case.

Yet I still get errors, or possibly an infinite loop. Any ideas?

str a1, bufferAddr stores the value from the register at the memory location pointed to by bufferAddr . Since this is in the middle of the init function it works first time only.

However ldr v2, =bufferAddr loads the value of bufferAddr , this results in in the result overwriting decrypt .

You should use ldr v2, bufferAddr .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM