3.10. STRING TO NUMBER CONVERSION (ATOI())
There is no instruction for multiplication by 10, two LEA instruction do this instead.
MSVC sometimes uses the ADD instruction with a negative constant instead of SUB. This is the case.
It’s very hard to say why this is better then SUB. But MSVC does this often.
Optimizing GCC 4.9.1 x64
Optimizing GCC 4.9.1 is more concise, but there is one redundant RET instruction at the end. One would
be enough.
Listing 3.23: Optimizing GCC 4.9.1 x64
my_atoi:
; load input character into EDX
movsx edx, BYTE PTR [rdi]
; EAX is allocated for "rt" variable
xor eax, eax
; exit, if loaded character is null byte
test dl, dl
je .L4
.L3:
lea eax, [rax+rax4]
; EAX=RAX5=rt5
; shift pointer to the next character:
add rdi, 1
lea eax, [rdx-48+rax2]
; EAX=input character - 48 + RAX2 = input character - '0' + rt10
; load next character:
movsx edx, BYTE PTR [rdi]
; goto loop begin, if loaded character is not null byte
test dl, dl
jne .L3
rep ret
.L4:
rep ret
Optimizing Keil 6/2013 (ARM mode)
Listing 3.24: Optimizing Keil 6/2013 (ARM mode)
my_atoi PROC
; R1 will contain pointer to character
MOV r1,r0
; R0 will contain "rt" variable
MOV r0,#0
B |L0.28|
|L0.12|
ADD r0,r0,r0,LSL #2
; R0=R0+R0<<2=rt5
ADD r0,r2,r0,LSL #1
; R0=input character + rt5<<1 = input character + rt*10
; correct whole thing by subtracting '0' from rt:
SUB r0,r0,#0x30
; shift pointer to the next character:
ADD r1,r1,#1
|L0.28|
; load input character to R2
LDRB r2,[r1,#0]
; is it null byte? if no, jump to loop body.
CMP r2,#0
BNE |L0.12|
; exit if null byte.
; "rt" variable is still in R0 register, ready to be used in caller function
BX lr
ENDP