############################################################################# # string.S - assembly string routines by Gordon Miller 2002 # AT&T Syntax - GCC calling convention - pentium align optimized ############################################################################# #include ############################################################################# # unsigned int gord_itoa (unsigned int i, char *a) ############################################################################# .section .bss # Section declaration .align 4 .lcomm revstr, INTLEN+1 # Reserve space for string ############################################################################# .text # Section declaration .align 16 .global gord_itoa # Entry point for linker .type gord_itoa,@function gord_itoa: pushl %edi # Save registers ... pushl %esi pushl %ebx pushl %ecx pushl %edx # Get reversed ascii string into 'revstr' ... myrevinit: movl 24(%esp), %eax # Put 'i' in eax xorl %ebx, %ebx # Initialize digit count movl $10, %ecx # Put 10 in ecx for divide movl $revstr, %edi # Put address of 'revstr' in edi movl 28(%esp), %esi # Put address of 'a' in esi mymore: xorl %edx, %edx # Initialize unsigned division divl %ecx # Divide 'i' by 10 addb $ASCZERO, %dl # Convert remainder digit to ascii movb %dl, (%edi, %ebx) # Move this digit to 'revstr' incl %ebx # Increment digit count testl %eax, %eax # While more digits ... jne mymore # ... round again movl %ebx, %eax # Return len # Reverse copy 'revstr' to 'a' myrevcopy: movb -1(%edi, %ebx), %dl # Move digit in 'revstr' ... movb %dl, (%esi) # ... to 'a' incl %esi # Next output digit decl %ebx # Decrement digit count ... jne myrevcopy # ... round again if more digits movb $0, (%esi) # Zero terminate 'a' popl %edx # Restore registers popl %ecx popl %ebx popl %esi popl %edi ret # Return from 'gord_itoa' .Lfe1: .size gord_itoa,.Lfe1-gord_itoa ############################################################################# # unsigned int gord_atoi (char *str) ############################################################################# .text # Section declaration .align 16 .global gord_atoi # Entry point for linker .type gord_atoi,@function gord_atoi: pushl %ebx # Save registers ... pushl %ecx pushl %edx pushl %esi xorl %eax, %eax # Initialize conversion movl 20(%esp), %esi # Pointer to string cmpb $0, (%esi) # Test for NULL string ... je myend2 # ... returns 0 xorl %ebx, %ebx # Clear ebx for char movl $10, %ecx # Load ecx with 10 for multiply mymore2: movb (%esi), %bl # Get char into bl subb $ASCZERO, %bl # Convert to digit jb mybad # Check bounds cmpb $9, %bl ja mybad addl %ebx, %eax # Add to running total js myflow # Check for little overflow incl %esi # Next char ... cmpb $0, (%esi) # ... test for end of string je myend2 mull %ecx # Multiply running total by 10 jc myflow # Check for overflow testl $0x80000000, %eax # Check for little overflow jne myflow jmp mymore2 # Round again ... mybad: movl $-2, %eax # Return -2 if bad string jmp myend2 myflow: movl $-1, %eax # Return -1 if overflow myend2: popl %esi # Restore registers popl %edx popl %ecx popl %ebx ret # Return from 'gord_atoi' .Lfe2: .size gord_atoi,.Lfe2-gord_atoi ############################################################################# # unsigned int gord_strlen (char *str) ############################################################################# .text # Section declaration .align 16 .global gord_strlen # Entry point for linker .type gord_strlen,@function gord_strlen: pushl %ebx # Save registers ... movl 8(%esp), %ebx # Pointer to string movl %ebx, %eax cmpb $0, (%eax) # Test for end of string je myend3 mymore3: incl %eax # Increase len count cmpb $0, (%eax) # Test for end of string ... jne mymore3 # ... round again myend3: subl %ebx, %eax # Length popl %ebx # Restore registers ret # Return from 'gord_strlen' .Lfe3: .size gord_strlen,.Lfe3-gord_strlen