【问题标题】:Concatenate two string in asm x86-64 intel syntax在 asm x86-64 intel 语法中连接两个字符串
【发布时间】:2020-08-11 17:05:59
【问题描述】:

我试图连接两个字符串,但我不断收到分段错误,有人可以帮助我解决我的代码可能有什么问题吗?谢谢! 为了测试它,我只是用动态分配的内存创建字符串,这是一个课堂练习,所以我必须从我的函数获得的 2 个参数中释放内存

我的代码:

    ;int32_t strCmp(char* a, char* b)
    strConcat:
        push rbp    ;stack frame 
        mov rbp, rsp
        push r12 ; stringA
        push r13 ; stringB
        push r14 ; puntero inicio ; stringA
        push r15 ; puntero inicio ; stringB   
        mov r12, rdi
        mov r13, rsi
        mov r14, r12
        mov r15, r13
        xor rcx, rcx ;clean rcx to do len(stringA)+leng(stringB)+1
        call strLen  ; len stringA
        add rcx, rax
        mov rdi, r13 
        call strLen  ;  len stringB
        add rcx, rax
        mov rdi, rcx
        inc rdi
        call malloc
        ; now rax has a pointer to new concatenated string space

        .cicloA:        ;loop to iterate over 1st string
            cmp byte [r12], 0
            jz .cicloB
            xor rdx, rdx
            mov dl, byte [r12]
            mov byte [rax], dl
            inc r12
            inc rax
            jmp .cicloA

        .cicloB:        ;loop to iterate over 2th string
            cmp byte [r13], 0
            jz .fin
            xor rdx, rdx
            mov dl, byte [r13]
            mov byte [rax], dl
            inc r13
            inc rax
            jmp .cicloB

        .fin:
            ;add /0
            mov byte [rax], 0
            ;release memory
            mov rdi, r14
            call free
            mov rdi, r15
            call free 
            pop r15
            pop r14
            pop r13
            pop r12
            pop rbp
            ret

而我的 strLen 函数是

    ;uint32_t strLen(char* a)
    strLen:
        push rbp    ;armo el stack frame 
        mov rbp, rsp
        xor rax,rax
        .avanzar:       ;loop para ver si llegue al fin de un string 
            cmp byte [rdi], 0   
            je .fin
            inc rdi
            inc rax
            jmp .avanzar
        .fin:
            pop rbp 
            ret

Valgrind 错误:

==18885== Invalid read of size 1
==18885==   at 0x400E4A: ??? (lib.asm:79)
==18885==   by 0x400C49: test_strConcat (main.c:79)
==18885==   by 0x400D28: main (main.c:109)
==18885== Address 0x2 is not stack'd, malloc'd or (recently) free'd

【问题讨论】:

  • lib.asm 中的第 79 行是哪一行代码?
  • 嗨! 77 .avanzar: ;循环检查是否是字符串的结尾 78 cmp byte [rdi], 0 79 je .fin 80 inc rdi 81 inc rax 82 jmp .avanzar 提前致谢
  • 如果你要调用strLen,只需使用这两个长度和指针来调用memcpy,而不是一次循环一个字节,再次搜索终止0 strLen 已经找到了!或者至少简化您的循环以使用已知长度而不是搜索0

标签: string assembly x86-64 nasm strcat


【解决方案1】:

最后,我从头重写了函数 strConcat,现在它可以工作了。

strConcat:
    push rbp    ;armo el stack frame 
    mov rbp, rsp
    push rbx
    push r12 ; stringA
    push r13 ; stringB
    sub rsp, 0X08

    mov r12, rdi
    mov r13, rsi

    call strLen     ;loongitud del primer string
    mov ebx, eax
    mov rdi, r13
    call strLen     ;longitud del segundo string;
    add ebx, eax
    mov edi, ebx
    add edi, 1
    call malloc
    ; ahora rax tiene el puntero a nuevo string para concatenar
    ;limpio contadores
    xor r8, r8
    xor r9, r9
    .cicloA:        ;loop para colocar stringA en nuevo string
        cmp byte [r12 + r8], 0
        jz .cicloB
        mov dl, byte [r12 + r8]
        mov byte [rax + r8], dl
        inc r8
        jmp .cicloA

    .cicloB:        ;loop para colocar stringB en nuevo string
        cmp byte [r13 + r9], 0
        jz .borrar
        mov dl, byte [r13 + r9]
        mov byte [rax + r8], dl
        inc r8
        inc r9
        jmp .cicloB

    .borrar:
        ;agrego el cero al final
        mov byte [rax + r8], 0
        mov rbx, rax
        ;reviso si son el mismo puntero
        cmp r12, r13
        je .igualitos

        ;libero memoria
        mov rdi, r12
        call free
        mov rdi, r13
        call free
        jmp .final
    .igualitos:
        mov rdi, r12
        call free
    .final:
        add rsp, 0x08
        mov rax, rbx
        pop r13
        pop r12
        pop rbx
        pop rbp
        ret

【讨论】:

  • 顺便说一句,strcat 在其输入上调用free() 是不正常的。如果来电者需要,他们可以单独进行。此外,如果您要这样做,je .igualitos 可以简单地跳过两个 free 调用中的 一个,因此您不需要重复的 mov rdi, r12 / call free jmp .final 在上面。
  • 感谢您提出让代码变得更好的建议。是的,我了解免费问题,只是这是他们要求的任务。
猜你喜欢
  • 2021-11-02
  • 2011-12-27
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多