2017-02-24 78 views
0

所以问题在于:我实际上正在尝试用汇编语言重新编译一些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一起工作(是的,我知道;))。

很多人会回答。 :)

+0

我会建议一个更具描述性的标题来获得更多关注。 –

+0

我建议不要这样的API,当目标无效时不要返回源代码。如果源是只读常量字符串,并且您将几个'strcat'调用链接在一起,出于某种原因,第一个失败的接收缓冲区为null(“new”失败?),则链中的下一个“strcat”将segfault,如果你重用'rax'的'buffer'指针(这与你的实际实现无关)。 – Ped7g

+0

例程正文看起来不错,但我认为只有'rdi == null'的情况才能正确释放堆栈。 'getdest:'会先将rdi放入rax中,然后第二次将下一个值(rbp?)放入rdi中。然后一切都会向南(哦,等等,它不,'leave'会救你,只有'rdi'不是缓冲区)......顺便说一句,在调试器中应该很容易看到,只需在'push rbp'并在'leave'处放置断点时注意你的'rsp','rsp'应该匹配。现在我记得'leave'的含义,实际上不是,'rsp'可以关闭,但你还是不想这样? – Ped7g

回答

0

最有可能的

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]