RosettaCodeData/Task/Determine-if-a-string-is-numeric/ARM-Assembly/determine-if-a-string-is-numeric.arm
2019-09-12 10:33:56 -07:00

199 lines
6.7 KiB
Text

/* ARM assembly Raspberry PI */
/* program strNumber.s */
/* Constantes */
.equ STDIN, 0 @ Linux input console
.equ STDOUT, 1 @ Linux output console
.equ EXIT, 1 @ Linux syscall
.equ READ, 3 @ Linux syscall
.equ WRITE, 4 @ Linux syscall
.equ BUFFERSIZE, 100
/* Initialized data */
.data
szMessNum: .asciz "Enter number : \n"
szMessError: .asciz "String is not a number !!!\n"
szMessInteger: .asciz "String is a integer.\n"
szMessFloat: .asciz "String is a float.\n"
szMessFloatExp: .asciz "String is a float with exposant.\n"
szCarriageReturn: .asciz "\n"
/* UnInitialized data */
.bss
sBuffer: .skip BUFFERSIZE
/* code section */
.text
.global main
main:
loop:
ldr r0,iAdrszMessNum
bl affichageMess
mov r0,#STDIN @ Linux input console
ldr r1,iAdrsBuffer @ buffer address
mov r2,#BUFFERSIZE @ buffer size
mov r7, #READ @ request to read datas
swi 0 @ call system
ldr r1,iAdrsBuffer @ buffer address
mov r2,#0 @ end of string
sub r0,#1 @ replace character 0xA
strb r2,[r1,r0] @ store byte at the end of input string (r0 contains number of characters)
ldr r0,iAdrsBuffer
bl controlNumber @ call routine
cmp r0,#0
bne 1f
ldr r0,iAdrszMessError @ not a number
bl affichageMess
b 5f
1:
cmp r0,#1
bne 2f
ldr r0,iAdrszMessInteger @ integer
bl affichageMess
b 5f
2:
cmp r0,#2
bne 3f
ldr r0,iAdrszMessFloat @ float
bl affichageMess
b 5f
3:
cmp r0,#3
bne 5f
ldr r0,iAdrszMessFloatExp @ float with exposant
bl affichageMess
5:
b loop
100: @ standard end of the program
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
svc 0 @ perform system call
iAdrszMessNum: .int szMessNum
iAdrszMessError: .int szMessError
iAdrszMessInteger: .int szMessInteger
iAdrszMessFloat: .int szMessFloat
iAdrszMessFloatExp: .int szMessFloatExp
iAdrszCarriageReturn: .int szCarriageReturn
iAdrsBuffer: .int sBuffer
/******************************************************************/
/* control if string is number */
/******************************************************************/
/* r0 contains the address of the string */
/* r0 return 0 if not a number */
/* r0 return 1 if integer eq 12345 or -12345 */
/* r0 return 2 if float eq 123.45 or 123,45 or -123,45 */
/* r0 return 3 if float with exposant eq 123.45E30 or -123,45E-30 */
controlNumber:
push {r1-r4,lr} @ save registers
mov r1,#0
mov r3,#0 @ point counter
1:
ldrb r2,[r0,r1]
cmp r2,#0
beq 5f
cmp r2,#' '
addeq r1,#1
beq 1b
cmp r2,#'-' @ negative ?
addeq r1,#1
beq 2f
cmp r2,#'+' @ positive ?
addeq r1,#1
2:
ldrb r2,[r0,r1] @ control space
cmp r2,#0 @ end ?
beq 5f
cmp r2,#' '
addeq r1,#1
beq 2b
3:
ldrb r2,[r0,r1]
cmp r2,#0 @ end ?
beq 10f
cmp r2,#'E' @ exposant ?
beq 6f
cmp r2,#'e' @ exposant ?
beq 6f
cmp r2,#'.' @ point ?
addeq r3,#1 @ yes increment counter
addeq r1,#1
beq 3b
cmp r2,#',' @ comma ?
addeq r3,#1 @ yes increment counter
addeq r1,#1
beq 3b
cmp r2,#'0' @ control digit < 0
blt 5f
cmp r2,#'9' @ control digit > 0
bgt 5f
add r1,#1 @ no error loop digit
b 3b
5: @ error detected
mov r0,#0
b 100f
6: @ float with exposant
add r1,#1
ldrb r2,[r0,r1]
cmp r2,#0 @ end ?
moveq r0,#0 @ error
beq 100f
cmp r2,#'-' @ negative exposant ?
addeq r1,#1
mov r4,#0 @ nombre de chiffres
7:
ldrb r2,[r0,r1]
cmp r2,#0 @ end ?
beq 9f
cmp r2,#'0' @ control digit < 0
blt 8f
cmp r2,#'9' @ control digit > 0
bgt 8f
add r1,#1
add r4,#1 @ counter digit
b 7b
8:
mov r0,#0
b 100f
9:
cmp r4,#0 @ number digit exposant = 0 -> error
moveq r0,#0 @ erreur
beq 100f
cmp r4,#2 @ number digit exposant > 2 -> error
movgt r0,#0 @ error
bgt 100f
mov r0,#3 @ valid float with exposant
b 100f
10:
cmp r3,#0
moveq r0,#1 @ valid integer
beq 100f
cmp r3,#1 @ number of point or comma = 1 ?
moveq r0,#2 @ valid float
movgt r0,#0 @ error
100:
pop {r1-r4,lr} @ restaur des 2 registres
bx lr @ return
/******************************************************************/
/* display text with size calculation */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
push {r0,r1,r2,r7,lr} @ save registers
mov r2,#0 @ counter length */
1: @ loop length calculation
ldrb r1,[r0,r2] @ read octet start position + index
cmp r1,#0 @ if 0 its over
addne r2,r2,#1 @ else add 1 in the length
bne 1b @ and loop
@ so here r2 contains the length of the message
mov r1,r0 @ address message in r1
mov r0,#STDOUT @ code to write to the standard output Linux
mov r7, #WRITE @ code call system "write"
svc #0 @ call system
pop {r0,r1,r2,r7,lr} @ restaur registers
bx lr @ return