C x86_64程序集字符串操作导致分段错误

C x86_64程序集字符串操作导致分段错误,c,macos,assembly,x86-64,nasm,C,Macos,Assembly,X86 64,Nasm,我正试图在汇编中编写一个“strcat”函数,但无法获取我传递给它以进行更改的内存中的值。我的考试失败了,我不明白为什么。我似乎也找不到任何易于理解的关于x86_64汇编的好文档 global _ft_strcat _ft_strcat: push rbx push rdx mov rbx, rsi mov rdx, rdi parse: cmp byte [rdx],

我正试图在汇编中编写一个“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);
}

我遗漏了include和header之类的内容,因为从我所看到的情况来看,这与问题无关。我通过一个调试器运行了这个程序,并注意到在我的函数结束时,rdi寄存器指向的字符串没有改变,但是我确实在concat标签中进行了循环,看起来从rsi指向的字符串中提取的值确实被复制到了dl寄存器中。

您的推送和弹出不匹配,因此您的例行更改
rbp
rbx
与保存它们的ABI要求相反。

我的问题是我不了解如何操作rdx寄存器的最低8位。通过将我的字符插入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

您会注意到添加了Rex寄存器,并使用其较低的8位复制字节。

非常感谢您的支持。我会更新这个问题。。。我没有注意到那个虫子。。。感谢您允许您在x86-64系统调用约定中对RDX、RCX、RAX、RSI、RDI和R8-R11进行重击。您不需要推送/弹出保存/还原它们。如果您避免使用RBX,则不需要任何推送/弹出。您还可以通过将条件分支放在循环的底部来保存指令,如
inc
/
cmp
/
jne parse
,就像普通的asm循环一样。不过,这确实需要注意避免一个接一个的错误。