NASM中的字符串长度计数器

时间:2013-06-28 14:01:47

标签: assembly 64-bit nasm

大家。我在NASM中编写了一个程序,计算作为变量提供的字符串的长度:

section .data
    ; str1 db '12345678901'
    str1 db '123456789012'

section .text
    global _start

_start:
    mov eax, str1
    mov ecx, -1

.loop:
    inc ecx
    cmp byte [eax + ecx], 0
    jne .loop

.done:
    mov eax, 1
    mov ebx, ecx
    int 80h

当我使用第一个字符串(在此清单中注释)运行程序时,它返回正确的值11.使用第二个字符串时,它比应该的值多13到1。我不知道为什么会这样。它是在64位机器上组装的。我尝试用GDB检查它,但我没有看到这一点......

3 个答案:

答案 0 :(得分:4)

str1 db '123456789012'
....    
cmp byte [eax + ecx], 0

您的字符串没有NULL终止符。将其更改为str1 db '123456789012',0

答案 1 :(得分:0)

计算字符串长度的最快方法是使用scasb指令:

xor   rax,rax      ;so all of ax is 0 for return value
mov   ecx,0x03fff  ;limit scan length
cld
repne scasb
sub   ecx,0x03fff  ;sub by the scan length
neg   ecx
dec   ecx          ;minus one for rep going too far by one
mov   eax,ecx      ;C functions return in ax register

0x3fff是我的限制值,以便在scasb未终止的字符串的情况下,0不会太远。您可以将其设置为您喜欢的任何值,实际上许多库在ecx的最大值时使用0xffffffff。但是你必须始终确保你给它的字符串0终止!如果没有,它将返回限制值作为字符串的长度(如果它没有先错误)。

答案 2 :(得分:0)

您可以在ecx中使用mov -1代替sub和neg,然后不使用

xor al, al      ; the byte that the scan will compare to is zero

mov ecx, -1     ; underfow will set the maximum number of bytes

cld             ; CLD (STD) clears (sets) the Direction flag, data goes onwards (backwards).
repne scasb     ; while [rdi] != al, keep scanning
; The REPNZ prefix (which is more readable in the REPNE form) repeats the scas as long as the comparison is false (REPeat while Not Equal) and ECX > 0. It also decrements ECX automatically in every iteration. ECX has been initialized to the longest possible string so that it doesn't terminate the loop early.

not ecx         ; Since ECX counts down from 0xffffffff (also known as -1), the resulting length will be -1-ECX
sub ecx, 1      ; len--

mov eax, ecx    ; ret = len

ret