flat assembler
Message board for the users of flat assembler.

Index > Main > fastest byte comparison in BIG loop?

Author
Thread Post new topic Reply to topic
thecf



Joined: 23 Dec 2006
Posts: 23
thecf 17 Feb 2007, 17:04
which is the fastest way to do a byte comparison in a big loop?

Code:
cmp  byte [esi+ecx],0
je     @f

or

mov  al,byte [esi+ecx]
test al,al
jz   @f
    
Post 17 Feb 2007, 17:04
View user's profile Send private message Reply with quote
tantrikwizard



Joined: 13 Dec 2006
Posts: 142
tantrikwizard 17 Feb 2007, 17:26
thecf wrote:
which is the fastest way to do a byte comparison in a big loop?

Code:
cmp  byte [esi+ecx],0
je     @f

or

mov  al,byte [esi+ecx]
test al,al
jz   @f
    


This code isnt in a loop, or its incomplete. Depending on your needs rep cmpsb may work better. Also, the first set of code should be faster because it removes the mov instruction. On the 486
Code:
test al, imm8    
takes 1 clock cycle while
Code:
test [m8], imm8    
takes 1/2 a cycle.
Code:
cmp [m16/32], imm    
take 1/2 a clock cycle. so the
Code:
mov al, [esi+ecx]
test al, al    
will be slower
Post 17 Feb 2007, 17:26
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
thecf



Joined: 23 Dec 2006
Posts: 23
thecf 17 Feb 2007, 17:32
ok I'm writing a string length function heres the code:

Code:
; in
; esi = string
; out
; ecx = string length
strlen:
xor  ecx,ecx
@@:
cmp  byte [esi+ecx],0
je   @f
inc  ecx
jmp  @b
@@:
ret
    
Post 17 Feb 2007, 17:32
View user's profile Send private message Reply with quote
tantrikwizard



Joined: 13 Dec 2006
Posts: 142
tantrikwizard 17 Feb 2007, 18:37
thecf wrote:
ok I'm writing a string length function heres the code:

Code:
; in
; esi = string
; out
; ecx = string length
strlen:
xor  ecx,ecx
@@:
cmp  byte [esi+ecx],0
je   @f
inc  ecx
jmp  @b
@@:
ret
    


It should work fine, theres many alternatives to string length functions. Heres one of mine:
Code:
;in
;edi = pointer to string string
;out
;eax = string length
_strlen:
        mov ecx, 0xffffffff
        xor eax, eax
        cld
        rep scasb
        mov eax, 0xffffffff
        sub eax, ecx
        ret
    
Post 17 Feb 2007, 18:37
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
asmfan



Joined: 11 Aug 2006
Posts: 392
Location: Russian
asmfan 17 Feb 2007, 18:52
OK, suggestions:
prefer registers over immediates, immediates over memory - store 0 in register
Post 17 Feb 2007, 18:52
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4623
Location: Argentina
LocoDelAssembly 17 Feb 2007, 19:12
Just an alternative but not sure if it's faster

Code:
;in 
;edi = pointer to string string 
;out 
;eax = string length 
_strlen: 
  mov     ecx, -1
  xor     eax, eax
  repne   scasb
  not     ecx
; Uncomment the line below if you don't want to include the NULL char
;  dec     ecx
  ret
    


The one I'm using in a small project is "inlined" and is this
Code:
  xor     ecx, ecx
  xor     eax, eax
  not     ecx
  repne   scasb
  not     ecx
  dec     ecx    
Post 17 Feb 2007, 19:12
View user's profile Send private message Reply with quote
MCD



Joined: 21 Aug 2004
Posts: 602
Location: Germany
MCD 17 Feb 2007, 23:17
tantrikwizard wrote:

Depending on your needs rep cmpsb may work better.

you mean scasb?
Post 17 Feb 2007, 23:17
View user's profile Send private message Reply with quote
IceStudent



Joined: 19 Dec 2003
Posts: 60
Location: Ukraine
IceStudent 21 Feb 2007, 19:18
if you want realy faster code, you should see on this function (from C runtime library):
Code:
        public  strlen
; int strlen (const char * str)
strlen:

        mov     ecx,[esp+4]       ; ecx -> string
        test    ecx,3                   ; test if string is aligned on 32 bits
        je      .main_loop

.str_misaligned:
        ; simple byte loop until string is aligned
        mov     al,byte [ecx]
        add     ecx,1
        test    al,al
        je      .byte_3
        test    ecx,3
        jne     .str_misaligned

        add     eax,dword 0         ; 5 byte nop to align label below

        align   16                      ; should be redundant

.main_loop:
        mov     eax,dword [ecx]     ; read 4 bytes
        mov     edx,7efefeffh
        add     edx,eax
        xor     eax,-1
        xor     eax,edx
        add     ecx,4
        test    eax,81010100h
        je      .main_loop
        ; found zero byte in the loop
        mov     eax,[ecx - 4]
        test    al,al                   ; is it byte 0
        je      .byte_0
        test    ah,ah                   ; is it byte 1
        je      .byte_1
        test    eax,00ff0000h           ; is it byte 2
        je      .byte_2
        test    eax,0ff000000h          ; is it byte 3
        je      .byte_3
        jmp     .main_loop         ; taken if bits 24-30 are clear and bit
                                        ; 31 is set

.byte_3:
        lea     eax,[ecx - 1]
        mov     ecx,[esp+4]
        sub     eax,ecx
        retn
.byte_2:
        lea     eax,[ecx - 2]
        mov     ecx,[esp+4]
        sub     eax,ecx
        retn
.byte_1:
        lea     eax,[ecx - 3]
        mov     ecx,[esp+4]
        sub     eax,ecx
        retn
.byte_0:
        lea     eax,[ecx - 4]
        mov     ecx,[esp+4]
        sub     eax,ecx
        retn
    
Post 21 Feb 2007, 19:18
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 26 Feb 2007, 20:18
Okay, this is probably not useful for most of you, but it works under DOS (or compatibles: e.g., DR-DOS, Win XP, etc.). The length in CX includes the terminating NUL. (No idea why there are two functions for the same thing.)

Ralf Brown wrote:

Category: DOS kernel
Flags: Undocumented function

INT 2F - DOS 3.0+ internal - GET LENGTH OF ASCIZ STRING

AX = 1212h
ES:DI -> ASCIZ string
Return: CX = length of string
SeeAlso: AX=1225h


Ralf Brown wrote:

Category: DOS kernel
Flags: Undocumented function

INT 2F - DOS 3.0+ internal - GET LENGTH OF ASCIZ STRING

AX = 1225h
DS:SI -> ASCIZ string
Return: CX = length of string
Note: supported by DR DOS 5.0+
SeeAlso: AX=1212h
Post 26 Feb 2007, 20:18
View user's profile Send private message Visit poster's website Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3174
Location: Denmark
f0dder 27 Feb 2007, 00:17
Fast string length?

Code:
mov eax, [edi.string.length]
    

Wink

The question of fast string length routines have been brought up countless times anyway, and it depends on various factors. For small/medium sized strings, one of the best approaches is the dword/masking thing that I first saw in agner fog's optimization manual.

For longer strings, MMX or SSE.
Post 27 Feb 2007, 00:17
View user's profile Send private message Reply with quote
Madis731



Joined: 25 Sep 2003
Posts: 2138
Location: Estonia
Madis731 27 Feb 2007, 11:39
http://www.azillionmonkeys.com/qed/asmexample.html (5.) and check the update from Norbert Juffa's discovery - this can be implemented to detect ANY byte value (except there was a problem with value 80h or 7Fh, can't remember).
Post 27 Feb 2007, 11:39
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.