491 lines
16 KiB
Plaintext
491 lines
16 KiB
Plaintext
/* ARM assembly Raspberry PI */
|
|
/* program routstring.s */
|
|
|
|
/* REMARK 1 : this program use routines in a include file
|
|
see task Include a file language arm assembly
|
|
for the routine affichageMess conversion10
|
|
see at end of this program the instruction include */
|
|
|
|
/*******************************************/
|
|
/* Constantes */
|
|
/*******************************************/
|
|
.include "../constantes.inc"
|
|
.equ BUFFERSIZE, 80
|
|
|
|
/*******************************************/
|
|
/* macros */
|
|
/*******************************************/
|
|
//.include "../../ficmacros32.inc" @ for developper debugging
|
|
|
|
/*********************************/
|
|
/* Initialized data */
|
|
/*********************************/
|
|
.data
|
|
szMessDebutPgm: .asciz "Program 32 bits start. \n"
|
|
szCarriageReturn: .asciz "\n"
|
|
szMessFinOK: .asciz "Program normal end. \n"
|
|
szMessErreur: .asciz "Error !!!\n"
|
|
szMessValString: .asciz "String value : "
|
|
szMessLenStr: .asciz "String length : "
|
|
szMessCopyString: .asciz "String copy : "
|
|
szMessEmpty: .asciz "String empty.\n"
|
|
szMessStrEqual: .asciz "Strings are equals.\n"
|
|
szMessStrNotEqual: .asciz "Strings are not equals.\n"
|
|
szMessStringfound: .asciz "String found at position :"
|
|
szMessStringJoint: .asciz "Joint string : "
|
|
szMessStringRep: .asciz "Replace occurences string : "
|
|
szMessBufferError: .asciz "Error : Buffer too small !!\n"
|
|
szString1: .asciz "ABCDE"
|
|
.equ LGSTRING1, . - szString1 - 1
|
|
szString2: .asciz ""
|
|
szString3: .asciz "ABCDF"
|
|
szString4: .asciz "CD"
|
|
szString5: .asciz "AABCIEFAAGHIAA"
|
|
szStringOcc: .asciz "AA"
|
|
szStringRep: .asciz "ZZ"
|
|
|
|
.align 4
|
|
/*********************************/
|
|
/* UnInitialized data */
|
|
/*********************************/
|
|
.bss
|
|
sZoneConv: .skip 24
|
|
szStringRec: .skip BUFFERSIZE
|
|
.align 4
|
|
|
|
/*********************************/
|
|
/* code section */
|
|
/*********************************/
|
|
.text
|
|
.global main
|
|
main:
|
|
ldr r0,iAdrszMessDebutPgm
|
|
bl affichageMess @ start message
|
|
|
|
ldr r0,iAdrszMessValString
|
|
bl affichageMess
|
|
ldr r0,iAdrszString1
|
|
bl affichageMess
|
|
ldr r0,iAdrszCarriageReturn
|
|
bl affichageMess
|
|
|
|
ldr r0,iAdrszMessLenStr
|
|
bl affichageMess
|
|
mov r0,#LGSTRING1 @ string length static
|
|
bl displayNumber
|
|
|
|
ldr r0,iAdrszMessLenStr
|
|
bl affichageMess
|
|
ldr r0,iAdrszString1
|
|
bl stringLen @ string length
|
|
bl displayNumber
|
|
|
|
|
|
ldr r0,iAdrszString1 @ string copy
|
|
ldr r1,iAdrszStringRec
|
|
mov r2,#BUFFERSIZE
|
|
bl copyString
|
|
cmp r0,#-1
|
|
beq 100f
|
|
ldr r0,iAdrszMessCopyString
|
|
bl affichageMess
|
|
ldr r0,iAdrszStringRec
|
|
bl affichageMess
|
|
ldr r0,iAdrszCarriageReturn
|
|
bl affichageMess
|
|
|
|
ldr r0,iAdrszString2 @ empty string
|
|
bl emptyString
|
|
|
|
ldr r0,iAdrszString1 @ string comparison
|
|
ldr r0,iAdrszString3
|
|
bl comparString
|
|
cmp r0,#0
|
|
bne 1f
|
|
ldr r0,iAdrszMessStrEqual
|
|
bl affichageMess
|
|
b 2f
|
|
1:
|
|
ldr r0,iAdrszMessStrNotEqual
|
|
bl affichageMess
|
|
2:
|
|
ldr r0,iAdrszString1 @ search substring
|
|
ldr r1,iAdrszString4
|
|
bl searchSubString
|
|
cmp r0,#-1
|
|
beq 3f
|
|
mov r1,r0
|
|
ldr r0,iAdrszMessStringfound
|
|
bl affichageMess
|
|
mov r0,r1
|
|
bl displayNumber
|
|
3:
|
|
ldr r0,iAdrszMessStringJoint @ joint strings
|
|
bl affichageMess
|
|
ldr r0,iAdrszString1
|
|
ldr r1,iAdrszString3
|
|
ldr r2,iAdrszStringRec
|
|
mov r3,#BUFFERSIZE
|
|
bl concatString
|
|
cmp r0,#-1
|
|
beq 100f
|
|
ldr r0,iAdrszStringRec
|
|
bl affichageMess
|
|
ldr r0,iAdrszCarriageReturn
|
|
bl affichageMess
|
|
|
|
ldr r0,iAdrszMessStringRep @ replace string or char
|
|
bl affichageMess
|
|
ldr r0,iAdrszString5 @ string
|
|
ldr r1,iAdrszStringOcc @ string occurence
|
|
ldr r2,iAdrszStringRep @ replace string
|
|
ldr r3,iAdrszStringRec @ buffer
|
|
mov r4,#BUFFERSIZE @ buffer size
|
|
bl replaceOccString
|
|
cmp r0,#-1
|
|
beq 100f
|
|
ldr r0,iAdrszStringRec
|
|
bl affichageMess
|
|
ldr r0,iAdrszCarriageReturn
|
|
bl affichageMess
|
|
|
|
ldr r0,iAdrszMessFinOK
|
|
bl affichageMess
|
|
b 100f
|
|
99:
|
|
ldr r0,iAdrszMessErreur @ error
|
|
bl affichageMess
|
|
mov r0, #1 @ return code error
|
|
b 100f
|
|
100:
|
|
mov r7,#EXIT @ program end
|
|
svc #0 @ system call
|
|
iAdrszMessDebutPgm: .int szMessDebutPgm
|
|
iAdrszMessFinOK: .int szMessFinOK
|
|
iAdrszMessErreur: .int szMessErreur
|
|
iAdrsZoneConv: .int sZoneConv
|
|
iAdrszMessLenStr: .int szMessLenStr
|
|
iAdrszMessValString: .int szMessValString
|
|
iAdrszMessCopyString: .int szMessCopyString
|
|
iAdrszMessStrEqual: .int szMessStrEqual
|
|
iAdrszMessStrNotEqual: .int szMessStrNotEqual
|
|
iAdrszMessStringfound: .int szMessStringfound
|
|
iAdrszMessStringJoint: .int szMessStringJoint
|
|
iAdrszMessStringRep: .int szMessStringRep
|
|
iAdrszString1: .int szString1
|
|
iAdrszString2: .int szString2
|
|
iAdrszString3: .int szString3
|
|
iAdrszString4: .int szString4
|
|
iAdrszString5: .int szString5
|
|
iAdrszStringRec: .int szStringRec
|
|
iAdrszStringOcc: .int szStringOcc
|
|
iAdrszStringRep: .int szStringRep
|
|
/***************************************************/
|
|
/* String length */
|
|
/***************************************************/
|
|
/* r0 contains string address */
|
|
/* r0 returns length */
|
|
stringLen:
|
|
push {r1,r2,lr} @ save registers
|
|
mov r1,#0 @ byte counter
|
|
1:
|
|
ldrb r2,[r0,r1] @ load byte
|
|
cmp r2,#0 @ final zero ?
|
|
moveq r0,r1 @ return counter
|
|
beq 100f
|
|
add r1,r1,#1 @ increment counter
|
|
b 1b @ and loop
|
|
100:
|
|
pop {r1,r2,pc} @ restaur registers
|
|
/***************************************************/
|
|
/* empty String */
|
|
/***************************************************/
|
|
/* r0 contains string address */
|
|
/* r0 returns 0 if string empty */
|
|
emptyString:
|
|
push {lr} @ save registers
|
|
ldrb r0,[r0] @ load first byte
|
|
cmp r0,#0
|
|
bne 100f
|
|
ldr r0,iAdrszMessEmpty
|
|
bl affichageMess
|
|
mov r0,#0
|
|
100:
|
|
pop {pc} @ restaur registers
|
|
iAdrszMessEmpty: .int szMessEmpty
|
|
/***************************************************/
|
|
/* String copy */
|
|
/***************************************************/
|
|
/* r0 contains string address */
|
|
/* r1 contains area string */
|
|
/* r2 contains area size */
|
|
copyString:
|
|
push {r3-r5,lr} @ save registers
|
|
mov r5,#0 @ indice
|
|
1:
|
|
ldrb r3,[r0,r5] @ load byte
|
|
strb r3,[r1,r5] @ store byte
|
|
cmp r3,#0 @ final zero ?
|
|
moveq r0,r5
|
|
beq 100f
|
|
add r5,r5,#1 @ increment indice
|
|
cmp r5,r2 @ > buffer size ?
|
|
bge 99f @ error
|
|
b 1b @ loop
|
|
99:
|
|
ldr r0,iAdrszMessBufferError
|
|
bl affichageMess
|
|
mov r0,#-1
|
|
100:
|
|
pop {r3-r5,pc} @ restaur registers
|
|
/***************************************************/
|
|
/* display number */
|
|
/***************************************************/
|
|
/* r0 contains number */
|
|
displayNumber:
|
|
push {r1,lr} @ save registers
|
|
ldr r1,iAdrsZoneConv
|
|
bl conversion10
|
|
ldr r0,iAdrsZoneConv
|
|
bl affichageMess
|
|
ldr r0,iAdrszCarriageReturn
|
|
bl affichageMess
|
|
100:
|
|
pop {r1,pc} @ restaur registers
|
|
iAdrszCarriageReturn: .int szCarriageReturn
|
|
/************************************/
|
|
/* String compare */
|
|
/************************************/
|
|
/* r0 et r1 contains strings address */
|
|
/* r0 returns 0 if equals -1 if less 1 if higter */
|
|
comparString:
|
|
push {r1-r4} @ save registers
|
|
mov r2,#0 @ indice
|
|
1:
|
|
ldrb r3,[r0,r2] @ load byte string 1
|
|
ldrb r4,[r1,r2] @ load byte string 2
|
|
cmp r3,r4
|
|
movlt r0,#-1 @ less
|
|
movgt r0,#1 @ hight
|
|
bne 100f @ not equal
|
|
cmp r3,#0 @ final zero ?
|
|
moveq r0,#0 @ equal
|
|
beq 100f @ and end
|
|
add r2,r2,#1 @ increment indice
|
|
b 1b @ and loop
|
|
100:
|
|
pop {r1-r4}
|
|
bx lr
|
|
/******************************************************************/
|
|
/* search a substring in the string */
|
|
/******************************************************************/
|
|
/* r0 contains the address of the input string */
|
|
/* r1 contains the address of substring */
|
|
/* r0 returns index of substring in string or -1 if not found */
|
|
searchSubString:
|
|
push {r1-r6,lr} @ save registers
|
|
mov r2,#0 @ counter byte input string
|
|
mov r3,#0 @ counter byte string
|
|
mov r6,#-1 @ index found
|
|
ldrb r4,[r1,r3]
|
|
1:
|
|
ldrb r5,[r0,r2] @ load byte string
|
|
cmp r5,#0 @ zero final ?
|
|
moveq r0,#-1 @ yes returns error
|
|
beq 100f
|
|
cmp r5,r4 @ compare character
|
|
beq 2f
|
|
mov r6,#-1 @ no equals - > raz index
|
|
mov r3,#0 @ and raz counter byte
|
|
add r2,#1 @ and increment counter byte
|
|
b 1b @ and loop
|
|
2: @ characters equals
|
|
cmp r6,#-1 @ first characters equals ?
|
|
moveq r6,r2 @ yes -> index begin in r6
|
|
add r3,#1 @ increment counter substring
|
|
ldrb r4,[r1,r3] @ and load next byte
|
|
cmp r4,#0 @ zero final ?
|
|
beq 3f @ yes -> end search
|
|
add r2,#1 @ else increment counter string
|
|
b 1b @ and loop
|
|
3:
|
|
mov r0,r6
|
|
100:
|
|
pop {r1-r6,lr} @ restaur registers
|
|
bx lr
|
|
/******************************************************************/
|
|
/* joint strings */
|
|
/******************************************************************/
|
|
/* r0 and r1 contains strings address */
|
|
/* r2 contains address buffer */
|
|
/* r3 contains buffer length */
|
|
concatString:
|
|
push {r3-r6,lr} @ save registers
|
|
mov r6,#0
|
|
mov r5,#0
|
|
1:
|
|
ldrb r4,[r0,r6] @ load byte string 1
|
|
cmp r4,#0 @ final zero ?
|
|
beq 2f
|
|
strb r4,[r2,r6] @ store byte in buffer
|
|
add r6,r6,#1 @ increment indice
|
|
cmp r6,r3 @ buffer max length ?
|
|
bge 99f @ error
|
|
b 1b @ else loop
|
|
|
|
2:
|
|
ldrb r4,[r1,r5] @ load byte string 2
|
|
strb r4,[r2,r6] @ store byte in buffer
|
|
cmp r4,#0 @ zero final ?
|
|
beq 3f @ end
|
|
add r6,r6,#1 @ increment indice
|
|
cmp r6,r3 @ buffer max length ?
|
|
bge 99f @ yes error
|
|
add r5,r5,#1 @ else loop
|
|
b 2b
|
|
3:
|
|
mov r0,r6
|
|
b 100f
|
|
99:
|
|
ldr r0,iAdrszMessBufferError
|
|
bl affichageMess
|
|
mov r0,#-1
|
|
|
|
100:
|
|
pop {r3-r6,pc} @ restaur registers
|
|
iAdrszMessBufferError: .int szMessBufferError
|
|
/******************************************************************/
|
|
/* replace occurences strings */
|
|
/******************************************************************/
|
|
/* r0 string address */
|
|
/* r1 occurence string address */
|
|
/* r2 replace string address */
|
|
/* r3 contains address buffer */
|
|
/* r4 contains buffer length */
|
|
replaceOccString:
|
|
push {r4-r6,lr} @ save registers
|
|
mov r12,r0
|
|
mov r11,r1
|
|
mov r9,#0 @ indice string
|
|
mov r6,#0 @ indice occurence
|
|
mov r8,#0 @ indice write buffer
|
|
mov r10,#-1 @ string occ start address
|
|
1:
|
|
ldrb r0,[r11,r6] @ load search byte
|
|
cmp r0,#0 @ final zero ?
|
|
beq 3f
|
|
2:
|
|
ldrb r7,[r12,r9] @ load string byte
|
|
cmp r7,#0 @ zero final ?
|
|
beq 6f
|
|
cmp r0,r7
|
|
bne 4f @ if not equal
|
|
cmp r10,#-1 @ string equal begin
|
|
moveq r10,r9 @ string equal begin = string indice
|
|
add r9,r9,#1 @ increment indice
|
|
add r6,r6,#1
|
|
b 1b @ loop
|
|
3: @ end of strings equals
|
|
mov r1,r8
|
|
bl replaceStr @ replace string
|
|
cmp r0,#-1 @ error ?
|
|
beq 99f
|
|
mov r8,r0
|
|
mov r6,#0 @ raz indice search
|
|
mov r10,#-1 @ raz string equal begin
|
|
b 1b
|
|
4: @ bytes not equals
|
|
cmp r10,#-1 @ if not string equal begin
|
|
beq 5f
|
|
41:
|
|
ldrb r0,[r12,r10] @ store bytes string
|
|
strb r0,[r3,r8]
|
|
add r8,r8,#1
|
|
cmp r8,r4
|
|
bge 99f
|
|
add r10,r10,#1
|
|
cmp r10,r9
|
|
blt 41b
|
|
mov r10,#-1 @ raz string equal begin
|
|
mov r6,#0 @ raz indice occurence
|
|
b 1b @ loop
|
|
|
|
5: @ byte not equal
|
|
str r7,[r3,r8] @ store byte string in buffer
|
|
add r8,r8,#1
|
|
cmp r8,r4 @ max buffer size ?
|
|
bge 99f @ error
|
|
add r9,r9,#1 @ inc indice chaine
|
|
mov r6,#0 @ raz indice occ
|
|
b 1b @ loop
|
|
|
|
6: @ end string
|
|
ldrb r0,[r11,r6] @ load search byte
|
|
cmp r0,#0 @ final zero
|
|
bne 7f
|
|
cmp r10,#-1 @
|
|
beq 100f
|
|
mov r1,r8
|
|
bl replaceStr @ replace
|
|
b 100f
|
|
7:
|
|
cmp r10,#-1 @ pas de char en cours
|
|
bne 8f
|
|
mov r0,#0
|
|
strb r0,[r3,r8] @ final zero
|
|
b 100f
|
|
8:
|
|
ldrb r0,[r12,r10] @ load string byte
|
|
strb r0,[r3,r8] @ store buffer byte
|
|
add r8,r8,#1
|
|
cmp r8,r4
|
|
bge 99f
|
|
add r10,r10,#1 @ increment begin string
|
|
cmp r10,r9 @ compare with position string
|
|
blt 8b @ loop
|
|
mov r0,#0
|
|
strb r0,[r3,r8] @ final zero
|
|
|
|
b 100f
|
|
99: @ buffer size error
|
|
ldr r0,iAdrszMessBufferError
|
|
bl affichageMess
|
|
mov r0,#-1
|
|
100:
|
|
pop {r4-r6,pc}
|
|
/******************************************************************/
|
|
/* replace occurences strings */
|
|
/******************************************************************/
|
|
/* r0 string address */
|
|
/* r1 indice to replace */
|
|
/* r2 replace string address */
|
|
/* r3 contains address buffer */
|
|
/* r4 contains buffer length */
|
|
/* r0 return new buffer position */
|
|
replaceStr:
|
|
push {r1-r6,lr} @ save registers
|
|
mov r5,#0
|
|
1:
|
|
ldrb r6,[r2,r5] @ load replace byte
|
|
cmp r6,#0 @ final zero
|
|
moveq r0,r1
|
|
beq 100f
|
|
strb r6,[r3,r1] @ store byte in buffer
|
|
add r1,r1,#1
|
|
cmp r1,r4 @ max size buffer ?
|
|
bge 99f @ error
|
|
add r5,r5,#1
|
|
b 1b
|
|
|
|
99:
|
|
ldr r0,iAdrszMessBufferError
|
|
bl affichageMess
|
|
mov r0,#-1
|
|
|
|
100:
|
|
pop {r1-r6,pc}
|
|
/***************************************************/
|
|
/* ROUTINES INCLUDE */
|
|
/***************************************************/
|
|
.include "../affichage.inc"
|