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