.globl memcmp memcmp: pushl %ebp # Save some registers movl %esp,%ebp pushl %edi movl 0x8(%ebp),%eax # Load S1 movl 0xc(%ebp),%edx # Load S2 movl 0x10(%ebp),%edi # Load length orl %edi,%edi # If no characters to be compared jz 7f # Exit immediately cmpl $0x10,%edi # For small strings jb 6f # we cannot afford startup overheads testb $3,%al # Check if S1 is already aligned jz 2f .align 16 1: movb (%eax),%cl # If not, compare byte-by-byte cmpb (%edx),%cl jne 9f # Until we have a mismatch incl %eax incl %edx decl %edi testb $3,%al # Or EAX is aligned jnz 1b .align 4 2: push %ebx # Save more callee-save regs push %esi testb $3,%dl # If EDX is aligned too jnz 4f # use simpler and faster code subl $4,%edi # Save a `cmp $4,%edi' below .align 16 3: movl (%edx),%esi # Compare a DWORD cmpl %esi,(%eax) jne 8f addl $4,%eax # Go on with the next one addl $4,%edx # if they match subl $4,%edi ja 3b addl $4,%edi # Restore the loop counter popl %esi # Beginning of epilog popl %ebx jmp 6f # And compare byte-by-byte .align 4 4: movl %edx,%ecx # Load the low bits of S2 into ECX andl $3,%ecx andl $~3,%edx # And align EDX to lower dword subl $4,%edi # Save a `cmp $4,%edi' below movl %ecx,%ebp # Save lower bits shll $3,%ecx # Byte offset --> bit offset movl (%edx),%esi # Load two DWORDs movl 0x4(%edx),%ebx .align 16 5: # Example: EDX was unaligned by 1, hence CL = 8 # # ESI EBX # ,-----.-----.-----.-----. ,-----.-----.-----.-----. # | 2 | 1 | 0 | -1 | | 6 | 5 | 4 | 3 | # `-----'-----'-----'-----' `-----'-----'-----'-----' # ,-. # | | # _| |_ after # \ / shrdl $8, %ebx, %esi # `v' # ESI EBX # ,-----.-----.-----.-----. ,-----.-----.-----.-----. # | 3 | 2 | 1 | 0 | | 6 | 5 | 4 | 3 | # `-----'-----'-----'-----' `-----'-----'-----'-----' # compared against (%eax) used for the next iteration # # ESI EBX # ,-----.-----.-----.-----. ,-----.-----.-----.-----. # | 6 | 5 | 4 | 3 | | 10 | 9 | 8 | 7 | # `-----'-----'-----'-----' `-----'-----'-----'-----' # # etc. shrdl %cl,%ebx,%esi # Compute an unaligned DWORD cmpl %esi,(%eax) # Compare it with the aligned EAX jne 8f movl %ebx,%esi movl 0x8(%edx),%ebx # Load another DWORD if they matched addl $4,%edx addl $4,%eax subl $4,%edi ja 5b orl %ebp,%edx # When few bytes remain, work again # on the unaligned EDX addl $4,%edi # Restore the loop counter popl %esi # Beginning of epilog popl %ebx .align 16 6: movb (%eax),%cl # Compare byte-by-byte cmpb (%edx),%cl jne 9f incl %eax # Go on if they matched incl %edx decl %edi jne 6b .align 16 7: xorl %eax,%eax # Return zero popl %edi # Epilog popl %ebp retl .align 16 8: movl (%eax),%ebx # Load the two mismatching DWORDs bswapl %esi # Make them big-endian bswapl %ebx cmpl %esi,%ebx # So that we can compare them popl %esi # Beginning of epilog popl %ebx .align 4 9: sbbl %eax,%eax # -1 if <, 0 if > orl $1,%eax # -1 if <, 1 if > popl %edi # Epilog popl %ebp retl