2017-02-24 47 views
0

ここに問題があります:実際にアセンブリ言語でclib関数の一部を再コンパイルしようとしています(これはアセンブリで始めるための学校プロジェクトです)。私が現在取り組んでいる機能はstrcatです。コピー先の文字列がNULLである場合StrCatをx86_64アセンブリで実装する

  • 、(RAXに)ソース文字列を返す:私の目標は、単純な、それを維持し、いくつかの次のルールに従うことである瞬間のために 。
  • ソース文字列がNULLの場合は、宛先文字列を(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、...)異なる方法の膨大な数を試してみましたが、常に同じ結果に到達しました:(我々はまだ文字列にそれを呼び出すことができるかどうか...)文字列の

  • とSegfault
  • 奇妙な文字

この現在のバージョンでは、宛先部分はそのまま残していますが、末尾に無人文字を追加しています(これは単なる例ですが、文字はしばしば変更される傾向があります)...
私は多分あなた私はインターネット上のすべてを見て、本当に私を助けてくれるものを見つけたことがないので、(少なくとも私は物事を変える場所や私のコードで間違っているかもしれないことのヒントを与える)助けてくれるかもしれません。

私はUbuntuでNasmと仕事をしています(はい、私は知っています))。

Thxは誰にでも答えます。 :)

+0

私はもっと注意を引くために、より記述的なタイトルを提案したいと思います。 –

+0

私はこのようなAPIに対して提案しますが、宛先が無効な場合はソースを返さないでください。ソースが読み込み専用の定数文字列であり、複数の 'strcat'呼び出しを連鎖させ、何らかの理由で最初に' null '( "new"が失敗しました)を受け取れなかった場合、チェーン内の次の 'strcat' 'rax'から' buffer'ポインタを再利用すると、セグメンテーションが解除されます(実際の実装とは無関係のコメントです)。 – Ped7g

+0

ルーチンの本体は大丈夫ですが、 'rdi == null'の場合だけスタックが正しく解放されると思います。 'getdest:'はrdiをraxに最初にポップし、次にrdiに次の値(rbp?)をポップします。そして、すべてが南に行く(ああ待って、それはしない、 '残してあなたを保存します、' rdi'だけバッファーではない)...BTWはデバッガで見やすいはずですが、 'push rbp'を実行して' rsp'を書き留め、 'leave'にブレークポイントを入れると、' rsp'がマッチするはずです。 、 '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は、関数の戻りADDRが含まれています。現在、あなたが「行き先」にいくつかのものを追加していたら、

mov  rdi, [rsp + 24] 
mov  rsi, [rsp + 32] 
関連する問題