0

指定された文字列の長さを取得するために NASM でコードを記述しようとしました。しかし、長さとしてガベージ値を与えます。コードは次のとおりです。

    section .data
        a db "nitin",10,0
        msg db "length = %d",10,0
    section .text
        global main
        extern printf
    main:
         nop
         xor eax,eax
         mov eax, a
         xor edx,edx
    length:
         mov dl, byte[eax]
         cmp dl,0
         je print
         inc eax
         jmp length

    print:
         pusha
         push eax
         push msg
         call printf
         add esp,8
         popa
    done:
         nop

結果が表示されます: 長さ = 132445678

私の間違いを整理するのを手伝ってもらえますか?

ありがとうございました

4

1 に答える 1

5

スニペットの EAX は、文字列のインデックスではなく、バイトのアドレスに従います。したがって、長さの代わりに、終端のヌル文字のアドレスを出力しています。

EAX をゼロから開始してアドレス [a + eax] のバイトを読み取るように再構成するか、長さを出力する前に EAX から a のアドレスを減算します。どちらでも動作します。

編集: 最初のアプローチでは、メイン ループは次のようになります。

main:
     nop
     xor eax,eax ; removed the mov eax,a line - eax stays zero
     xor edx,edx
length:
     mov dl, byte[a+eax]         ; eax is the index in the string
     cmp dl,0
     ;The rest stays the same

2 番目のアプローチでは、ループは同じままですが、印刷部分は余分に取得されますsub

print:
     sub eax, offset b ; convert from address to index
     pusha
     push eax
     push msg
     ; The rest is the same

ただし、これが最短の方法です。

main:
    nop
    mov edi, a ; the string we're scanning
    xor al, al ; That's what we're scanning the string for - a null valued byte
    mov ecx, 0ffffffffh ; we bet on string being null terminated - no hard limit on string scanning
    repne scasb ; Once this finishes, ECX is (0xffffffff - length - 1) (because the terminating null is counted too)
    mov eax, 0fffffffeh
    sub eax, ecx    ; Now eax is (0xffffffff - 1 - ecx), which is string length
print:
    ; Same as before

scasコマンドとrepxxプレフィックスを使用する方法を調べてください。C RTL (strlen、strcpy など) の一部が Intel CPU 命令セットに実装されているかのようです。

余談ですが、このスニペットには 2 つの完全に関係のない行があります -xor eax, eaxそしてxor edx, edx関数の先頭にあります。両方とも、次の行で上書きされるレジスタをゼロにします。

于 2013-03-14T14:49:51.007 に答える