使用NASM的字符串长度

时间:2013-03-14 14:42:46

标签: assembly x86 nasm

我试图在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

你能帮我解决一下我的错误吗?

谢谢

1 个答案:

答案 0 :(得分:6)

您的代码段中的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

对于第二种方法,循环保持不变,但打印部分得到额外的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前缀一起使用。这几乎就像在英特尔CPU指令集中实现了一部分C RTL(strlen,strcpy等)。

在旁注中,该代码段在函数的开头有两条完全无关的行 - xor eax, eaxxor edx, edx。两者都将一个寄存器归零,无论如何都会在下一行中被覆盖。