1

每个人。我在 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 检查它,但我不明白这一点......

4

3 回答 3

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

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

于 2013-06-28T14:17:38.443 回答
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终止的!如果不是,它将返回限制值作为字符串的长度(如果它没有首先出错)。

于 2013-06-28T17:07:16.207 回答
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
于 2018-12-09T16:20:22.440 回答