Reputation: 1576
everyone. I wrote a program in NASM calculating length of a string supplied as a variable:
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
When I run the program with the first string (commented in this listing) it returns the correct value 11. With the second string it's 13 - 1 more than it should be. I have no idea why it is so. It's assembled on a 64-bit machine. I tried inspecting it with GDB, but I don't see the point...
Upvotes: 1
Views: 4462
Reputation: 11259
Instead of sub and neg you may use mov -1 in ecx: and then not
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
Upvotes: 1
Reputation:
The fastest way to calculate a string's length is to use the scasb instruction:
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
The 0x3fff
is my limiting value so that the scasb
doesn't go too far in case of a string that's not 0
terminated. You can set it to any value you like, in fact many libraries use ecx
at its max of 0xffffffff
. But you must always be sure the strings you give it are 0
terminated! If not, it will return the limit value as the string's length (if it doesn't fault first).
Upvotes: 1
Reputation: 58507
str1 db '123456789012'
....
cmp byte [eax + ecx], 0
Your string has no NUL terminator. Change it to str1 db '123456789012',0
.
Upvotes: 4