尝试在 at&t 程序集中编写 strcpy,没有输出

Trying to write strcpy in assembly at&t, no output

我正在尝试用汇编、at&t 语法编写 char *my_strcpy(char *dest, const char *source);,它应该与 C 中的 strcpy 完全一样。我的 c 文件如下所示:

.globl my_strcpy

my_strcpy:
    push %rbp
    mov %rsp, %rbp
    mov %rdi, %rax
    jmp copy_loop

跳转毫无意义

copy_loop:
    cmp [=11=], (%rsi)

您没有指定这应该是 8、16、32 还是 64 位比较。当我 assemble 它时,我得到一个 32 位比较;例如它查看地址 %rsi 处的 32 位字是否为零。您需要将其更改为 cmpb [=17=], (%rsi).

    je end
    mov %rsi, %rdi

正如用户 500 所指出的,这会将 %rsi 寄存器中的地址复制到 %rdi 寄存器中,并覆盖它。这不是你想要的。你可能想要像 movb (%rsi), (%rdi) 这样的指令,但实际上不存在这样的指令:x86 没有这样一条指令来将内存移动到内存(特殊例外:参见 movsb 指令)。因此,您需要先将地址 %rsi 处的字节复制到寄存器中,然后使用另一条指令将其向前复制,例如mov (%rsi), %cl ; mov %cl, (%rdi)。请注意,使用 8 位 %cl 寄存器可以清楚地表明这些应该是一个字节的移动。

movzbl (%rsi), %ecx 是在现代 x86 上加载字节的更有效方式。您仍然通过使用 mov %cl, (%rdi) 读取 CL 来存储它,但是覆盖整个 RCX 而不是合并到 RCX 中更好。

    addq , %rsi
    addq , %rdi

您可能想了解 inc 指令,但 add 没问题。

    je copy_loop

我想你的意思是jmp copy_loop,因为这里的跳转应该是无条件发生的。 (或者你应该重新安排你的循环,这样条件分支就可以在底部。因为你想复制终止 0 字节,你可以只复制然后 然后 检查 0 , 比如 do{}while(c != 0))

end:
    leave
    ret