3.10. STRING TO NUMBER CONVERSION (ATOI())
Optimizing Keil 6/2013 (Thumb mode)
Listing 3.25: Optimizing Keil 6/2013 (Thumb mode)
my_atoi PROC
; R1 will be pointer to the input character
MOVS r1,r0
; R0 is allocated to "rt" variable
MOVS r0,#0
B |L0.16|
|L0.6|
MOVS r3,#0xa
; R3=10
MULS r0,r3,r0
; R0=R3R0=rt10
; shift pointer to the next character:
ADDS r1,r1,#1
; correct whole thing by subtracting 0' character from it':
SUBS r0,r0,#0x30
ADDS r0,r2,r0
; rt=R2+R0=input character + (rt*10 - '0')
|L0.16|
; load input character to R2
LDRB r2,[r1,#0]
; is it zero?
CMP r2,#0
; jump to loop body if it is not
BNE |L0.6|
; rt variable in R0 now, ready to be used in caller function
BX lr
ENDP
Interestingly,fromschoolmathematicswemayrecallthattheorderofadditionandsubtractionoperations
doesn’t matter.
That’s our case: first, thert∗ 10 −′ 0 ′expression is computed, then the input character value is added to it.
Indeed, the result is the same, but the compiler did some regrouping.
Optimizing GCC 4.9.1 ARM64
The ARM64 compiler can use the pre-increment instruction suffix:
Listing 3.26: Optimizing GCC 4.9.1 ARM64
my_atoi:
; load input character into W1
ldrb w1, [x0]
mov x2, x0
; X2=address of input string
; is loaded character zero?
; jump to exit if its so
; W1 will contain 0 in this case.
; it will be reloaded into W0 at L4.
cbz w1, .L4
; W0 will contain "rt" variable
; initialize it at zero:
mov w0, 0
.L3:
; subtract 48 or '0' from input variable and put result into W3:
sub w3, w1, #48
; load next character at address X2+1 into W1 with pre-increment:
ldrb w1, [x2,1]!
add w0, w0, w0, lsl 2
; W0=W0+W0<<2=W0+W04=rt5
add w0, w3, w0, lsl 1
; W0=input digit + W0<<1 = input digit + rt52 = input digit + rt*10
; if the character we just loaded is not null byte, jump to the loop begin
cbnz w1, .L3