Search code examples
assemblyx86-64reverse-engineering

Deciphering simple assembly code: is it strcpy or strcat?


1  .text
2  .globl mystery
3  .type mystery, @function

4  mystery:
5  movq %rdi, %rax
6  movq %rdi, %rdx
7  cmpb $0, (%rdi)
8  je .L5

9  .L3:
10 addq $1, %rdx
11 cmpb $0, (%rdx)
12 jne .L3

13 .L5:
14 addq $1, %rsi
15 movb -1(%rsi), %cl
16 addq $1, %rdx
17 movb %cl, -1(%rdx)
18 cmpb $0, %cl
19 jne .L5

20 ret

I am really confused about this one. Is it an implementation of strcpy or strcat. Also, I understand that the first loop searches for the null terminator of the string, and the second loop does the same but also makes a copy of the string, but I am having a hard time wrapping my head around what the entire function is doing. Is it copying string stored at %rdi to another location (strcpy) or is it adding string stored at %rsi to the end of %rdi (strcat).


Solution

  • With pseudo-C comments

    1  .text
    2  .globl mystery
    3  .type mystery, @function
    
    4  mystery:
    5  movq %rdi, %rax      # rax = rdi
    6  movq %rdi, %rdx      # rdx = rdi
    7  cmpb $0, (%rdi)      # *(char*)rdi == 0 ?
    8  je .L5               # Jump if equal (zero)
    
    9  .L3:
    10 addq $1, %rdx        # ++rdx
    11 cmpb $0, (%rdx)      # *(char*)rdx == 0?
    12 jne .L3              # Jump if not equal (non zero)
    
    13 .L5:
    14 addq $1, %rsi        # ++rsi
    15 movb -1(%rsi), %cl   # cl = *((char*)rsi - 1)
    16 addq $1, %rdx        # ++rdx
    17 movb %cl, -1(%rdx)   # *((char*)rdx - 1) = cl
    18 cmpb $0, %cl         # Is cl == 0 ?
    19 jne .L5              # Jump if not equal
    
    20 ret
    

    So rewriting it into C code:

    char* func(char* rsi, char *rdi) {
        char *dest = rdi;   // rdx 
        char *src  = rsi;   // rsi
        char c;
    
        // Find first '\0'
        if (*dest != 0)
            while (*++dest != 0)
                ;
    
        // Copy from src until '\0' reached
        do {
            c = *src++;
            *dest++ = c;
        } while (c != 0)
    
        return rdi; // rax
    }
    

    So we see that this is strcat() because it first skips the existing string and then copies.