在x86_64程序集中实现StrCat
问题描述:
所以问题在于:我实际上正在尝试用汇编语言重新编译一些clib函数(这是一个帮助程序集开始的学校项目)。我目前正在使用的功能是strcat。 就目前我的目标是要保持它的简单,并按照如下几个规则:在x86_64程序集中实现StrCat
- 如果目标字符串是NULL,返回(在RAX)源字符串。
- 如果源字符串为NULL,则返回(in rax)目标字符串。
- 将源字符串复制到目标字符串的末尾(包括终止0)并返回(仍然以rax结尾)结果。
这里是我的代码:
ft_strcat:
push rbp
mov rbp, rsp ; saving the stack state
push rdi ; seems to work better this way but I don't know why
mov rdi, [rsp + 24] ; destination string
mov rsi, [rsp + 16] ; source string
push rdi ; keeping the adress to return
test rsi, rsi ; in case one of the strings is NULL
je getdest
test rdi, rdi
je getsrc
toend: ; to go to the end of the destination string
cmp byte [rdi], 0x0 ; is it the end?
je cpy ; if so, go to the next part
inc rdi ; else keep going
jmp toend ; loop
cpy: ; to copy the source string to the end of the destination string
mov al, byte[rsi] ; getting the byte to copy
mov byte [rdi], al ; copying it
cmp byte [rsi], 0x0 ; it is the end of the source string?
je getdest ; if so, jump to the end
inc rdi ; else increase counter
inc rsi
jmp cpy ; loop
getdest: ; if source is NULL or copy is done
pop rax
jmp end
getsrc: ; if destination is NULL
mov rax, rsi
end:
pop rdi ; get rdi back
leave
ret ; finally return...
我已经尝试不同的方式一个巨大数字(MOVSB,经过论证与寄存器[直接],改变寄存器...)总是达到相同的结果:
- 段错误
- 字符串中奇怪的字符(如果我们仍然可以把它串...)
这个最新版本保持目的地部分完好,但在年底将那些没有字符的字符:���Ph�
(这只是一个例子,但人物往往在一段时间换一次)...
我想,也许你可以帮助我(至少让我知道在哪里可以改变事情,或者我的代码中可能有什么错误),因为我已经浏览了整个互联网,并且从未发现能够真正帮助我的事情。
哦,顺便说一句,我在Ubuntu上与Nasm一起工作(是的,我知道;))。
很多人会回答。 :)
答
最有可能的
mov rdi, [rsp + 32] ; destination string
mov rsi, [rsp + 24] ; source string
或
mov rdi, [rbp + 24] ; destination string
mov rsi, [rbp + 16] ; source string
无论你更喜欢
在当前的版本中,RSI包含返回地址的功能。如果你目前正在追加一些东西到'目的地',然后尝试
mov rdi, [rsp + 24]
mov rsi, [rsp + 32]
我会建议一个更具描述性的标题来获得更多关注。 –
我建议不要这样的API,当目标无效时不要返回源代码。如果源是只读常量字符串,并且您将几个'strcat'调用链接在一起,出于某种原因,第一个失败的接收缓冲区为null(“new”失败?),则链中的下一个“strcat”将segfault,如果你重用'rax'的'buffer'指针(这与你的实际实现无关)。 – Ped7g
例程正文看起来不错,但我认为只有'rdi == null'的情况才能正确释放堆栈。 'getdest:'会先将rdi放入rax中,然后第二次将下一个值(rbp?)放入rdi中。然后一切都会向南(哦,等等,它不,'leave'会救你,只有'rdi'不是缓冲区)......顺便说一句,在调试器中应该很容易看到,只需在'push rbp'并在'leave'处放置断点时注意你的'rsp','rsp'应该匹配。现在我记得'leave'的含义,实际上不是,'rsp'可以关闭,但你还是不想这样? – Ped7g