rendered paste body#############################################################################
# string.S - assembly string routines by Gordon Miller 2002
# AT&T Syntax - GCC calling convention - pentium align optimized
#############################################################################
#include <gord-asm/gord-asm.h>
#############################################################################
# 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