Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 尝试在汇编at&;中写入strcpy;t、 无输出_String_Loops_Pointers_Assembly_Att - Fatal编程技术网

String 尝试在汇编at&;中写入strcpy;t、 无输出

String 尝试在汇编at&;中写入strcpy;t、 无输出,string,loops,pointers,assembly,att,String,Loops,Pointers,Assembly,Att,我正在尝试编写char*my_strcpy(char*dest,const char*source)在汇编、at&t语法中,其行为应该与C中的strcpy完全相同。我的C文件如下所示: .globl my_strcpy my_strcpy: push %rbp mov %rsp, %rbp mov %rdi, %rax jmp copy_loop 这种跳跃毫无意义 copy_loop: cmp $0, (%rsi) 您没有指定这是8位、16位、32位

我正在尝试编写
char*my_strcpy(char*dest,const char*source)在汇编、at&t语法中,其行为应该与C中的strcpy完全相同。我的C文件如下所示:

.globl my_strcpy

my_strcpy:
    push %rbp
    mov %rsp, %rbp
    mov %rdi, %rax
    jmp copy_loop
这种跳跃毫无意义

copy_loop:
    cmp $0, (%rsi)
您没有指定这是8位、16位、32位还是64位比较。当我组装它时,我得到一个32位的比较;e、 g.它查看地址
%rsi
处的32位字是否等于零。您需要将其更改为
cmpb$0,(%rsi)

如用户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 $1, %rsi
    addq $1, %rdi
您可能想了解
inc
指令,但是
add
可以

    je copy_loop
我想你的意思是
jmp copy_loop
,因为这里的跳转应该无条件发生。(或者您应该重新安排循环,使条件分支可以位于底部。由于您希望复制终止的
0
字节,您可以只复制并检查0,就像
do{}while(c!=0)


我自己不使用AT&t语法,但我很确定这个
mov%rsi,%rdi
只是将
rsi
中的指针复制到
rdi
。要移动字节,您需要执行类似于
mov(%rsi),%al;mov%al,(%rdi)
。我试图执行movb%rsi,%rdi,但它显示的参数太多。你的意思是它在返回之前会先断开故障?你应该这么说,而不仅仅是“什么都不输出”!请注意,
strcpy
应该返回
char*
,而不是
size\u t
,返回值应该等于
dest
。这是你的代码实际做的,但可能不是你认为它做的。不要破坏你的问题。我回滚了删除了大部分问题的编辑。谢谢,我已经理解了我的错误,但是除了保存到%al寄存器中,还有其他方法一次移动1个字节吗?@catrev:是的,正如这个答案已经显示的,您可以将它加载到
%cl
或任何其他您想要的8位寄存器中!或者使用
movsb
,就像这个答案也提到的那样,但这是缓慢的。(如果您关心性能,那么在找到对齐边界后,您可以使用SSE2一次复制16个字节。)这样我就可以使用任何寄存器了?@catrev:嗯,您已经在使用
%rax
存储返回值,因此除非您更改它,否则您不能使用
%al
%ah
。而
%rbx
是被调用方保存的寄存器,因此除非要保存和还原
%rbx
,否则不能使用
%bl
%bh
。这就是我选择
%cl
@catrev:显然不是
sil
dil
的原因,因为这样会破坏指针值。但是,是的,任何一个电话都会被打坏。另外,请参阅我对该答案的更新;您忘记复制终止的
0
字节,因为在存储它之前要离开循环。
    je copy_loop
end:
    leave
    ret