I have got an assembly function strcmp, which I use with C. This is the function-
; strcmp-
;   takes rdi and rsi as the string
;   this function always returns 0 if strings were equal, else 1, stored in rax
BITS 64
section .text
    global strcmp
strcmp:
    push r15
    push r14
    mov r15, 0
    jmp strcmp_loop
strcmp_loop:
    mov r14, [rdi+r15]
    cmp r14, [rsi+r15] ; compare s1[i] and s2[i]
    jne exit_fail
    cmp r14, 0 ; compare s1[i] with NULL. No need to do the same with s2[i] since s1[i] and s2[i] will be equal at this point
    je exit_success
    inc r15
    jmp strcmp_loop
exit_success:
    mov rax, 0
    jmp exit
exit_fail:
    mov rax, 1
    jmp exit
exit:
    pop r14
    pop r15
    ret
And io_funcs.c-
#include "io_funcs.h"
int main() {
    char s[] = "Hello World!\n", test[14];
    puts(s);
    strcpy(test, s);
    puts(test);
    if(!strcmp(s, test)) {
        puts("Equal!!!! :-)");
    } else {
        puts("Unequal!!! :-(");
    }
    putc('\n');
    return 0;
}
which I compile with gcc o/* c/io_funcs.c -static -nostdlib (I assemble my assembly programs in directory o/ using nasm). When I run it, I get-
$ ./a.out 
Hello World!
Hello World!
Unequal!!! :-(
When I try debugging it a bit, I get-
$ gdb ./a.out -q
Reading symbols from ./a.out...
(gdb) b strcmp
Breakpoint 1 at 0x401120: file asm/strcmp.asm, line 10.
(gdb) run
Starting program: /home/spot/coding/asm/io_funcs/a.out 
Hello World!
Hello World!
Breakpoint 1, strcmp () at asm/strcmp.asm:10
10          push r15
(gdb) p (char *)$rdi
$1 = 0x7fffffffe16a "\210\341\377\377\377\177"
(gdb) p (char *)$rsi
$2 = 0x7fffffffe15c "Hello World!\n"
(gdb) p (char *)$rdx
$3 = 0x7fffffffe15c "Hello World!\n"
(gdb)
This seems to mean that rsi and rdx contain the arguments, and rdi maybe just garbage (or something else?).
When I replace this line
    if(!strcmp(s, test)) {
with this
    if(!strcmp("Hello World!\n", test)) {
the program seems to give me this-
$ gdb ./a.out -q
Reading symbols from ./a.out...
(gdb) b strcmp
Breakpoint 1 at 0x401120: file asm/strcmp.asm, line 10.
(gdb) run
Starting program: /home/spot/coding/asm/io_funcs/a.out 
Hello World!
Hello World!
Breakpoint 1, strcmp () at asm/strcmp.asm:10
10          push r15
(gdb) p (char *)$rdi
$1 = 0x402000 "Hello World!\n"
(gdb) p (char *)$rsi
$2 = 0x7fffffffe15c "Hello World!\n"
(gdb)
but also gives the output Unequal!!! :-(.
But when I replace the similar line with
    if(!strcmp("Hello World!\n", "Hello World!\n")) {
the program seems to give me correct output-
$ ./a.out 
Hello World!
Hello World!
Equal!!!! :-)
Why does this happen? And how can I solve it?
Also note that all the functions that I am using, have been implemented by me, by my own in assembly (just for a practice of assembly). And they all seem to work except for the strcmp function.
Edit-
After following the advice of checking my strings after strcpy execution in the comments, I see that string s has been changed.
$ gdb ./a.out -q
Reading symbols from ./a.out...
(gdb) b 8
Breakpoint 1 at 0x40105f: file c/io_funcs.c, line 8.
(gdb) run
Starting program: /home/spot/coding/asm/io_funcs/a.out 
Hello World!
Breakpoint 1, main () at c/io_funcs.c:8
8           puts(test);
(gdb) p (char *)test
$1 = 0x7fffffffe15c "Hello World!\n"
(gdb) p (char *)s
$2 = 0x7fffffffe16a "\210\341\377\377\377\177"
(gdb)
(Note that strcpy executes at line 7, so I am checking this right after the function call.)
So, I might have done a mistake in my strcpy function. Please check for any errors that you might see in it-
strcpy.asm-
; strcpy-
;   takes rdi and rsi as the string
;   this function always returns 0, stored in rax
BITS 64
section .text
    global strcpy
strcpy:
    push r15
    push r14
    mov r15, 0
    jmp strcpy_loop
strcpy_loop:
    mov r14, [rsi+r15]
    mov [rdi+r15], r14
    cmp [rsi+r15], byte 0
    je exit
    inc r15
    jmp strcpy_loop
exit:
    mov rax, 0
    pop r14
    pop r15
    ret