Манипулирование строкой сборки x86_64 вызывает ошибку сегментации - PullRequest
1 голос
/ 08 октября 2019

Я пытаюсь написать функцию "strcat" в сборке и не могу получить значения в памяти, которую я передаю, чтобы изменить. Мои тесты терпят крах, и я не понимаю почему. Кажется, я не могу найти хорошую документацию по сборке x86_64 в удобном для понимания виде.

    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

Выше написана функция, которую я пытаюсь написать, а ниже - мой тест.

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

Я пропустил такие вещи, как включает в себя и мой заголовок, потому что это не имеет отношения к вопросу из того, что я вижу. Я запустил это через отладчик и заметил, что в конце моей функции строка, на которую указывает регистр rdi, не изменилась, но я делаю цикл в метке concat, и похоже, что значения извлекаются из строкиуказываемый rsi действительно копируется в регистр dl.

Ответы [ 2 ]

2 голосов
/ 08 октября 2019

Ваши нажатия и всплывающие окна не совпадают, поэтому ваши обычные изменения rbp и rbx противоречат требованию ABI для их сохранения.

0 голосов
/ 08 октября 2019

Моя проблема заключалась в том, что я не понимал, как я манипулировал младшими 8 битами регистра rdx. Вставляя моего персонажа в dl, его значение обновляло общее значение rdx, что означало, что я фактически не конкатенировал строку, которую имел, но я записывал в области памяти, о которых я не знал, что я записывал.

Код теперь выглядит следующим образом

    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

Вы заметите добавление регистра Рекса и использование его младших 8 битов для копирования байтов свыше.

...