大家。我在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检查它,但我没有看到这一点......
答案 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