Gladwin Mohlamonyane
Gladwin Mohlamonyane

Reputation: 13

x86_64 assembly string manipulation causes segmentation fault

I am trying to write a "strcat" function in assembly and can't get the values in the memory I pass it to change. My tests are crashing and I don't understand why. I can't seem to find any good documentation on x86_64 assembly in an easy to digest manner either.

    global  _ft_strcat

_ft_strcat:
        push    rbx
        push    rdx
        mov     rbx, rsi
        mov     rdx, rdi
parse:
        cmp     byte [rdx], 0
        je      concat
        inc     rdx
        jmp     parse
concat:
        cmp     BYTE[rbx], 0
        je      finish
        mov     dl, BYTE[rbx]
        mov     BYTE[rdx], dl
        inc     rdx
        inc     rbx
        jmp     concat
finish:
        mov     BYTE[rdx], 0
        mov     rax, rdi
        pop     rdx
        pop     rbx
        ret

The above is the function I am trying to write and below is my test.

int             main(void)
{
        char    buffer[50] = "Hello, ";
        ft_strcat(buffer, "World!");
        printf("%s\n", buffer);
        return (0);
}

I left out things such as includes and my header because that is not relevant to the question from what I can see. I ran this through a debugger and noticed that at the end of my function, the string pointed to by the rdi register has not changed, but I do go through the loop in the concat label and it looks like the values being extracted from the string being pointed to by rsi is indeed being copied into the dl register.

Upvotes: 1

Views: 293

Answers (2)

Gladwin Mohlamonyane
Gladwin Mohlamonyane

Reputation: 13

My problem was my lack of understand how I was manipulating the rdx register's lowest 8-bits. By inserting my character into dl, its value updated the overall value of rdx, which meant that I was not actually concatenating the string I had, but I was writing into regions of memory I didn't know I was writing into.

The code now looks like this

    global  _ft_strcat

_ft_strcat:
        push    rbx
        push    rdx
        push    rcx
        xor     rcx, rcx
        mov     rbx, rsi
        mov     rdx, rdi
parse:
        cmp     byte [rdx], 0
        je      concat
        inc     rdx
        jmp     parse
concat:
        cmp     BYTE[rbx], 0
        je      finish
        mov     cl, BYTE[rbx]
        mov     BYTE[rdx], cl
        inc     rdx
        inc     rbx
        jmp     concat
finish:
        mov     BYTE[rdx], 0
        pop     rcx
        pop     rdx
        pop     rbx
        mov     rax, rdi
        ret

You will notice the addition of the Rex register and the use of its lower 8 bits for copying bytes over.

Upvotes: 0

Timothy Baldwin
Timothy Baldwin

Reputation: 3675

Your pushes and pops don't match so your routine changes rbp and rbx contrary to the ABI requirement to preserve them.

Upvotes: 2

Related Questions