【问题标题】:Length of a string using NASM使用 NASM 的字符串长度
【发布时间】:2026-02-05 06:05:01
【问题描述】:

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

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

谢谢你

【问题讨论】:

    标签: assembly x86 nasm


    【解决方案1】:

    您的 sn-p 中的 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 前缀一起使用。就好像 C RTL 的一部分(strlen、strcpy 等)是在 Intel CPU 指令集中实现的。

    顺便说一句,sn-p 有两条完全无关的行——函数开头的xor eax, eaxxor edx, edx。两者都将寄存器清零,无论如何都会在下一行被覆盖。

    【讨论】:

    • 感谢您的友好回复。我已经使用计数器寄存器 ecx 解决了它。但是,我想知道如何使用eax解决它,对不起导师,我仍然没有得到如何使用eax解决它。
    • 其实最快的方法是rep scasb al=0。让您完全避免循环。
    • 很棒的分析。学生只需要这个。太棒了,我的导师
    • 你能告诉我如何只打印 DL 中的数据吗?
    • 请提出一个单独的问题。我不明白你想要什么。
    最近更新 更多