Works with: as version Raspberry Pi  or android 32 bits with application Termux
/* ARM assembly Raspberry PI  */
/*  program filterdes.s   */

/************************************/
/* Constantes                       */
/************************************/
/* for constantes see task include a file in arm assembly */
.include "../constantes.inc"

/************************************/
/* Initialized data                 */
/************************************/
.data
szMessResult:        .asciz "Start array : "
szMessResultFil:     .asciz "Filter array : "
szMessResultdest:    .asciz "Same array : "
szMessStart:         .asciz "Program 32 bits start.\n"
szCarriageReturn:    .asciz "\n"
.align 4
arrayNumber:         .int 1,2,3,4,5,6,7,8,9,10
.equ LGARRAY,   (. - arrayNumber) / 4
/************************************/
/* UnInitialized data               */
/************************************/
.bss
.align 4
arrayNumberFil:           .skip 4 * LGARRAY  @ result array
sZoneConv:                .skip 24
/************************************/
/*  code section                    */
/************************************/
.text
.global main
main:
    ldr r0,iAdrszMessStart      @ display start message
    bl affichageMess
    ldr r0,iAdrszMessResult     @ display message
    bl affichageMess
    ldr r5,iAdrarrayNumber      @ start array address
    mov r4,#0                   @ index

1:
    ldr r0,[r5,r4,lsl #2]       @ load a value
    ldr r1,iAdrsZoneConv
    bl conversion10             @ décimal conversion
    add r1,r1,r0                @ compute address end number
    add r1,#2                   @ add two characters
    mov r0,#0                   @ for limit the size of display number
    strb r0,[r1]                @ to store a final zero
    ldr r0,iAdrsZoneConv
    bl affichageMess            @ display value
    add r4,r4,#1                @ increment index
    cmp r4,#LGARRAY             @ end array ?
    blt 1b                      @ no -> loop
    ldr r0,iAdrszCarriageReturn
    bl affichageMess

    ldr r6,iAdrarrayNumberFil   @ adrress result array
    mov r4,#0                   @ index
    mov r3,#0                   @ index result
2:
    ldr r0,[r5,r4,lsl #2]       @ load a value
    tst r0,#1                   @ odd ?
    streq r0,[r6,r3,lsl #2]     @ no -> store in result array
    addeq r3,r3,#1              @ and increment result index
    add r4,r4,#1                @ increment array index
    cmp r4,#LGARRAY             @ end ?
    blt 2b                      @ no -> loop

    ldr r0,iAdrszMessResultFil
    bl affichageMess
    mov r4,#0                   @ init index

3:                              @ display filter result array
    ldr r0,[r6,r4,lsl #2]
    ldr r1,iAdrsZoneConv
    bl conversion10
    add r1,r1,r0
    add r1,#2
    mov r0,#0
    strb r0,[r1]
    ldr r0,iAdrsZoneConv
    bl affichageMess
    add r4,r4,#1
    cmp r4,r3
    blt 3b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess

                                @ array destruction
    mov r4,#0                   @ index
    mov r3,#0                   @ index result
4:
    ldr r0,[r5,r4,lsl #2]       @ load a value
    tst r0,#1                   @ even ?
    bne 6f
    cmp r3,r4                   @ index =  no store
    beq 5f
    str r0,[r5,r3,lsl #2]       @ store in free item on same array
5:
    add r3,r3,#1                @ and increment result index
6:
    add r4,r4,#1                @ increment array index
    cmp r4,#LGARRAY             @ end ?
    blt 4b                      @ no -> loop

    ldr r0,iAdrszMessResultdest
    bl affichageMess
    mov r4,#0                   @ init index

7:                              @ display array
    ldr r0,[r5,r4,lsl #2]
    ldr r1,iAdrsZoneConv
    bl conversion10
    add r1,r1,r0
    add r1,#2
    mov r0,#0
    strb r0,[r1]
    ldr r0,iAdrsZoneConv
    bl affichageMess
    add r4,r4,#1
    cmp r4,r3
    blt 7b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess

100:                             @ standard end of the program
    mov r0, #0                   @ return code
    mov r7, #EXIT                @ request to exit program
    svc 0                        @ perform the system call
iAdrszCarriageReturn:    .int szCarriageReturn
iAdrszMessStart:         .int szMessStart
iAdrarrayNumber:         .int arrayNumber
iAdrszMessResult:        .int szMessResult
iAdrarrayNumberFil:      .int arrayNumberFil
iAdrszMessResultFil:     .int szMessResultFil
iAdrszMessResultdest:    .int szMessResultdest
iAdrsZoneConv:           .int sZoneConv
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
/* for this file see task include a file in language ARM assembly*/
.include "../affichage.inc"

select certain elements from an array into a new array in a generic way. Specifically, it selects all even numbers from an array. Optionally, it can also filter destructively by modifying the original array instead of creating a new one.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program substring.s   */

/* Constantes    */
.equ STDOUT, 1                           @ Linux output console
.equ EXIT,   1                           @ Linux syscall
.equ WRITE,  4                           @ Linux syscall

.equ BUFFERSIZE,          100

/* Initialized data */
.data
szMessString:            .asciz "Result : "
szString1:               .asciz "abcdefghijklmnopqrstuvwxyz"
szStringStart:           .asciz "abcdefg"
szCarriageReturn:        .asciz "\n"

/* UnInitialized data */
.bss
szSubString:             .skip 500             @ buffer result

/*  code section */
.text
.global main
main:

    ldr r0,iAdrszString1                        @ address input string
    ldr r1,iAdrszSubString                      @ address output string
    mov r2,#22                                  @ location
    mov r3,#4                                   @ length
    bl subStringNbChar                          @ starting from n characters in and of m length
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString                      @ display substring result
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
    @
    ldr r0,iAdrszString1
    ldr r1,iAdrszSubString
    mov r2,#15                                  @ location
    bl subStringEnd                             @starting from n characters in, up to the end of the string
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
    @
    ldr r0,iAdrszString1
    ldr r1,iAdrszSubString
    bl subStringMinus                           @ whole string minus last character
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
    @
    ldr r0,iAdrszString1
    ldr r1,iAdrszSubString
    mov r2,#'c'                                 @ start character
    mov r3,#5                                   @ length
    bl subStringStChar                          @starting from a known character within the string and of m length
    cmp r0,#-1                                  @ error ?
    beq 2f
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
    @
2:
    ldr r0,iAdrszString1
    ldr r1,iAdrszSubString
    ldr r2,iAdrszStringStart                    @ sub string to start
    mov r3,#10                                  @ length
    bl subStringStString                        @ starting from a known substring within the string and of m length
    cmp r0,#-1                                  @ error ?
    beq 3f
    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszSubString
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                 @ display line return
    bl affichageMess
3:
100:                                            @ standard end of the program
    mov r0, #0                                  @ return code
    mov r7, #EXIT                               @ request to exit program
    svc 0                                       @ perform system call
iAdrszMessString:         .int szMessString
iAdrszString1:            .int szString1
iAdrszSubString:            .int szSubString
iAdrszStringStart:            .int szStringStart
iAdrszCarriageReturn:     .int szCarriageReturn
/******************************************************************/
/*     sub strings  index start  number of characters             */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r2 contains the start index                  */
/* r3 contains numbers of characters to extract */
/* r0 returns number of characters or -1 if error */
subStringNbChar:
    push {r1-r5,lr}                             @ save  registers
    mov r4,#0                                   @ counter byte output string
1:
    ldrb r5,[r0,r2]                             @ load byte string input
    cmp r5,#0                                   @ zero final ?
    beq 2f
    strb r5,[r1,r4]                             @ store byte output string
    add r2,#1                                   @ increment counter
    add r4,#1
    cmp r4,r3                                   @ end ?
    blt 1b                                      @ no -> loop
2:
    mov r5,#0
    strb r5,[r1,r4]                             @ load byte string 2
    mov r0,r4
100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr                                       @ return
/******************************************************************/
/*     sub strings  index start at end of string             */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r2 contains the start index                  */
/* r0 returns number of characters or -1 if error */
subStringEnd:
    push {r1-r5,lr}                             @ save registers
    mov r4,#0                                   @ counter byte output string
1:
    ldrb r5,[r0,r2]                             @ load byte string 1
    cmp r5,#0                                   @ zero final ?
    beq 2f
    strb r5,[r1,r4]
    add r2,#1
    add r4,#1
    b 1b                                        @ loop
2:
    mov r5,#0
    strb r5,[r1,r4]                             @ load byte string 2
    mov r0,r4
100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr
/******************************************************************/
/*      whole string minus last character                        */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r0 returns number of characters or -1 if error */
subStringMinus:
    push {r1-r5,lr}                             @ save  registers
    mov r2,#0                                   @ counter byte input string
    mov r4,#0                                   @ counter byte output string
1:
    ldrb r5,[r0,r2]                             @ load byte string
    cmp r5,#0                                   @ zero final ?
    beq 2f
    strb r5,[r1,r4]
    add r2,#1
    add r4,#1
    b 1b                                        @  loop
2:
    sub r4,#1
    mov r5,#0
    strb r5,[r1,r4]                             @ load byte string 2
    mov r0,r4
100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr
/******************************************************************/
/*   starting from a known character within the string and of m length  */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r2 contains the character    */
/* r3 contains the length
/* r0 returns number of characters or -1 if error */
subStringStChar:
    push {r1-r5,lr}                             @ save  registers
    mov r6,#0                                   @ counter byte input string
    mov r4,#0                                   @ counter byte output string

1:
    ldrb r5,[r0,r6]                             @ load byte string
    cmp r5,#0                                   @ zero final ?
    streqb r5,[r1,r4]
    moveq r0,#-1
    beq 100f
    cmp r5,r2
    beq 2f
    add r6,#1
    b 1b                                        @  loop
2:
    strb r5,[r1,r4]
    add r6,#1
    add r4,#1
    cmp r4,r3
    bge 3f
    ldrb r5,[r0,r6]                             @ load byte string
    cmp r5,#0
    bne 2b
3:
    mov r5,#0
    strb r5,[r1,r4]                             @ load byte string 2
    mov r0,r4
100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr

/******************************************************************/
/*   starting from a known substring within the string and of m length  */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of the output string */
/* r2 contains the address of string to start    */
/* r3 contains the length
/* r0 returns number of characters or -1 if error */
subStringStString:
    push {r1-r8,lr}                             @ save  registers
    mov r7,r0                                   @ save address
    mov r8,r1                                   @ counter byte string
    mov r1,r2
    bl searchSubString
    cmp r0,#-1
    beq 100f
    mov r6,r0                                   @ counter byte input string
    mov r4,#0
1:
    ldrb r5,[r7,r6]                             @ load byte string
    strb r5,[r8,r4]
    cmp r5,#0                                   @ zero final ?
    moveq r0,r4
    beq 100f
    add r4,#1
    cmp r4,r3
    addlt r6,#1
    blt 1b                                      @  loop
    mov r5,#0
    strb r5,[r8,r4]
    mov r0,r4
100:
    pop {r1-r8,lr}                              @ restaur registers
    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

/******************************************************************/
/*     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

- Extracts a substring starting from the nth character of a specific length m.
- Extracts a substring starting from the nth character up to the end of the string.
- Returns the entire string excluding the last character.
- Extracts a substring starting from a known character within the string of length m.
- Extracts a substring starting from a known substring within the string of length m.
- Supports any valid Unicode code point, including those in the Basic Multilingual Plane or above it.
- References logical characters (code points), not 8-bit code units for UTF-8 or 16-bit code units for UTF-16.
- Does not necessarily support all Unicode characters for other encodings like 8-bit ASCII, or EUC-JP.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program avltree2.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                              */
/*******************************************/
.equ STDOUT, 1           @ Linux output console
.equ EXIT,   1           @ Linux syscall
.equ WRITE,  4           @ Linux syscall
.equ BRK,    0x2d        @ Linux syscall
.equ CHARPOS,     '@'

.equ NBVAL,    12

/*******************************************/
/* Structures                               */
/********************************************/
/* structure tree     */
    .struct  0
tree_root:                             @ root pointer (or node right)
    .struct  tree_root + 4
tree_size:                             @ number of element of tree
    .struct  tree_size + 4
tree_suite:
    .struct  tree_suite + 12           @ for alignement to node
tree_fin:
/* structure node tree */
    .struct  0
node_right:                            @ right pointer
    .struct  node_right + 4
node_left:                             @ left pointer
    .struct  node_left + 4
node_value:                            @ element value
    .struct  node_value + 4
node_height:                          @ element value
    .struct  node_height + 4
node_parent:                          @ element value
    .struct  node_parent + 4
node_fin:
/* structure queue*/
    .struct  0
queue_begin:                           @ next pointer
    .struct  queue_begin + 4
queue_end:                             @ element value
    .struct  queue_end + 4
queue_fin:
/* structure node queue    */
    .struct  0
queue_node_next:                       @ next pointer
    .struct  queue_node_next + 4
queue_node_value:                      @ element value
    .struct  queue_node_value + 4
queue_node_fin:
/*******************************************/
/* Initialized data                        */
/*******************************************/
.data
szMessPreOrder:       .asciz "PreOrder :\n"
szCarriageReturn:     .asciz "\n"
/* datas error display */
szMessErreur:         .asciz "Error detected.\n"
szMessKeyDbl:         .asciz "Key exists in tree.\n"
szMessInsInv:         .asciz "Insertion in inverse order.\n"
/* datas message display */
szMessResult:         .asciz "Ele: @ G: @ D: @ val @ h @ pere @\n"
sValue:               .space 12,' '
                      .asciz "\n"
/*******************************************/
/* UnInitialized data                      */
/*******************************************/
.bss
sZoneConv:            .skip 24
stTree:               .skip tree_fin    @ place to structure tree
stTree1:              .skip tree_fin    @ place to structure tree
stQueue:              .skip queue_fin   @ place to structure queue
/*******************************************/
/*  code section                           */
/*******************************************/
.text
.global main
main:
    mov r8,#1                           @ node tree value
1:                                      @ loop insertion in order
    ldr r0,iAdrstTree                   @ structure tree address
    mov r1,r8
    bl insertElement                    @ add element value r1
    cmp r0,#-1
    beq 99f
    //ldr r3,iAdrstTree                 @ tree root address (begin structure)
    //ldr r0,[r3,#tree_root]
    //ldr r1,iAdrdisplayElement           @ function to execute
    //bl preOrder
    add r8,#1                           @ increment value
    cmp r8,#NBVAL                       @ end ?
    ble 1b                              @ no -> loop

    ldr r0,iAdrstTree                   @ structure tree address
    mov r1,#11                          @ verif key dobble
    bl insertElement                    @ add element value r1
    cmp r0,#-1
    bne 2f
    ldr r0,iAdrszMessErreur
    bl affichageMess
2:
    ldr r0,iAdrszMessPreOrder           @ load verification
    bl affichageMess
    ldr r3,iAdrstTree                   @ tree root address (begin structure)
    ldr r0,[r3,#tree_root]
    ldr r1,iAdrdisplayElement           @ function to execute
    bl preOrder

    ldr r0,iAdrszMessInsInv
    bl affichageMess
    mov r8,#NBVAL                       @ node tree value
3:                                      @ loop insertion inverse order
    ldr r0,iAdrstTree1                  @ structure tree address
    mov r1,r8
    bl insertElement                    @ add element value r1
    cmp r0,#-1
    beq 99f
    sub r8,#1                           @ increment value
    cmp r8,#0                           @ end ?
    bgt 3b                              @ no -> loop

    ldr r0,iAdrszMessPreOrder           @ load verification
    bl affichageMess
    ldr r3,iAdrstTree1                  @ tree root address (begin structure)
    ldr r0,[r3,#tree_root]
    ldr r1,iAdrdisplayElement           @ function to execute
    bl preOrder

                                        @ search value
    ldr r0,iAdrstTree1                  @ tree root address (begin structure)
    mov r1,#11                          @ value to search
    bl searchTree
    cmp r0,#-1
    beq 100f
    mov r2,r0
    ldr r0,iAdrszMessKeyDbl             @ key exists
    bl affichageMess
                                        @ suppresssion previous value
    mov r0,r2
    ldr r1,iAdrstTree1
    bl supprimer

    ldr r0,iAdrszMessPreOrder           @ verification
    bl affichageMess
    ldr r3,iAdrstTree1                  @ tree root address (begin structure)
    ldr r0,[r3,#tree_root]
    ldr r1,iAdrdisplayElement           @ function to execute
    bl preOrder

    b 100f
99:                                     @ display error
    ldr r0,iAdrszMessErreur
    bl affichageMess
100:                                    @ standard end of the program
    mov r7, #EXIT                       @ request to exit program
    svc 0                               @ perform system call
iAdrszMessPreOrder:        .int szMessPreOrder
iAdrszMessErreur:          .int szMessErreur
iAdrszCarriageReturn:      .int szCarriageReturn
iAdrstTree:                .int stTree
iAdrstTree1:               .int stTree1
iAdrstQueue:               .int stQueue
iAdrdisplayElement:        .int displayElement
iAdrszMessInsInv:          .int szMessInsInv
/******************************************************************/
/*     insert element in the tree                                 */
/******************************************************************/
/* r0 contains the address of the tree structure */
/* r1 contains the value of element              */
/* r0 returns address of element or - 1 if error */
insertElement:                        @ INFO: insertElement
    push {r1-r8,lr}                   @ save  registers
    mov r7,r0                         @ save head
    mov r0,#node_fin                  @ reservation place one element
    bl allocHeap
    cmp r0,#-1                        @ allocation error
    beq 100f
    mov r5,r0
    str r1,[r5,#node_value]           @ store value in address heap
    mov r3,#0
    str r3,[r5,#node_left]            @ init left pointer with zero
    str r3,[r5,#node_right]           @ init right pointer with zero
    str r3,[r5,#node_height]          @ init balance with zero
    ldr r2,[r7,#tree_size]            @ load tree size
    cmp r2,#0                         @ 0 element ?
    bne 1f
    str r5,[r7,#tree_root]            @ yes -> store in root
    b 4f
1:                                    @ else search free address in tree
    ldr r3,[r7,#tree_root]            @ start with address root
2:                                    @ begin loop to insertion
    ldr r4,[r3,#node_value]           @ load key
    cmp r1,r4
    beq 6f                            @ key equal
    blt 3f                            @ key <
                                      @ key >  insertion right
    ldr r8,[r3,#node_right]           @ node empty ?
    cmp r8,#0
    movne r3,r8                       @ no -> next node
    bne 2b                            @ and loop
    str r5,[r3,#node_right]           @ store node address in right pointer
    b 4f
3:                                    @ left
    ldr r8,[r3,#node_left]            @ left pointer empty ?
    cmp r8,#0
    movne r3,r8                       @
    bne 2b                            @ no -> loop
    str r5,[r3,#node_left]            @ store node address in left pointer
4:
    str r3,[r5,#node_parent]          @ store parent
    mov r4,#1
    str r4,[r5,#node_height]          @ store height = 1
    mov r0,r5                         @ begin node to requilbrate
    mov r1,r7                         @ head address
    bl equilibrer

5:
    add r2,#1                        @ increment tree size
    str r2,[r7,#tree_size]
    mov r0,#0
    b 100f
6:                                   @ key equal ?
    ldr r0,iAdrszMessKeyDbl
    bl affichageMess
    mov r0,#-1
    b 100f
100:
    pop {r1-r8,lr}                    @ restaur registers
    bx lr                             @ return
iAdrszMessKeyDbl:           .int szMessKeyDbl
/******************************************************************/
/*     equilibrer after insertion                                    */
/******************************************************************/
/* r0 contains the address of the node       */
/* r1 contains the address of head */
equilibrer:                       @ INFO: equilibrer
    push {r1-r8,lr}               @ save  registers
    mov r3,#0                     @ balance factor
1:                                @ begin loop
    ldr r5,[r0,#node_parent]      @ load father
    cmp r5,#0                     @ end ?
    beq 5f
    cmp r3,#2                     @ right tree too long
    beq 5f
    cmp r3,#-2                    @ left tree too long
    beq 5f
    mov r6,r0                     @ s = current
    ldr r0,[r6,#node_parent]      @ current = father
    ldr r7,[r0,#node_left]
    cmp r7,#0
    ldrne r8,[r7,#node_height]     @ height left tree
    moveq r8,#0
    ldr r7,[r0,#node_right]
    cmp r7,#0
    ldrne r9,[r7,#node_height]     @ height right tree
    moveq r9,#0
    cmp r8,r9
    addgt r8,#1
    strgt r8,[r0,#node_height]
    addle r9,#1
    strle r9,[r0,#node_height]
    //
    ldr r7,[r0,#node_right]
    cmp r7,#0
    ldrne r8,[r7,#node_height]
    moveq r8,#0
    ldr r7,[r0,#node_left]
    cmp r7,#0
    ldrne r9,[r7,#node_height]
    moveq r9,#0
    sub r3,r8,r9                    @ compute balance factor
    b 1b
5:
    cmp r3,#2
    beq 6f
    cmp r3,#-2
    beq 6f
    b 100f
6:
    mov r3,r1
    mov r4,r0
    mov r1,r6
    bl equiUnSommet
                                      @ change head address ?
    ldr r2,[r3,#tree_root]
    cmp r2,r4
    streq r6,[r3,#tree_root]
100:
    pop {r1-r8,lr}                    @ restaur registers
    bx lr                             @ return
/******************************************************************/
/*     equilibre 1 sommet                                     */
/******************************************************************/
/* r0 contains the address of the node       */
/* r1 contains the address of the node    */
equiUnSommet:                             @ INFO: equiUnSommet
    push {r1-r9,lr}                       @ save  registers
    mov r5,r0                             @ save p
    mov r6,r1    // s
    ldr r2,[r5,#node_left]
    cmp r2,r6
    bne 5f
    ldr r7,[r5,#node_right]
    cmp r7,#0
    moveq r8,#0
    ldrne r8,[r7,#node_height]
    ldr r7,[r5,#node_left]
    cmp r7,#0
    moveq r9,#0
    ldrne r9,[r7,#node_height]
    sub r3,r8,r9
    cmp r3,#-2
    bne 100f
    ldr r7,[r6,#node_right]
    cmp r7,#0
    moveq r8,#0
    ldrne r8,[r7,#node_height]
    ldr r7,[r6,#node_left]
    cmp r7,#0
    moveq r9,#0
    ldrne r9,[r7,#node_height]
    sub r3,r8,r9
    cmp r3,#1
    bge 2f
    mov r0,r5
    bl rotRight
    b 100f
2:
    mov r0,r6
    bl rotLeft
    mov r0,r5
    bl rotRight
    b 100f

5:
    ldr r7,[r5,#node_right]
    cmp r7,#0
    moveq r8,#0
    ldrne r8,[r7,#node_height]
    ldr r7,[r5,#node_left]
    cmp r7,#0
    moveq r9,#0
    ldrne r9,[r7,#node_height]
    sub r3,r8,r9
    cmp r3,#2
    bne 100f
    ldr r7,[r6,#node_right]
    cmp r7,#0
    moveq r8,#0
    ldrne r8,[r7,#node_height]
    ldr r7,[r6,#node_left]
    cmp r7,#0
    moveq r9,#0
    ldrne r9,[r7,#node_height]
    sub r3,r8,r9
    cmp r3,#-1
    ble 2f
    mov r0,r5
    bl rotLeft
    b 100f
2:
    mov r0,r6
    bl rotRight
    mov r0,r5
    bl rotLeft
    b 100f

100:
    pop {r1-r9,lr}                    @ restaur registers
    bx lr                             @ return
/******************************************************************/
/*     right rotation                                     */
/******************************************************************/
/* r0 contains the address of the node       */
rotRight:                           @ INFO: rotRight
    push {r1-r5,lr}                 @ save  registers
    //   r2                  r2
    //      r0                   r1
    //   r1                         r0
    //      r3                    r3
    ldr r1,[r0,#node_left]          @ load left children
    ldr r2,[r0,#node_parent]        @ load father
    cmp r2,#0                       @ no father ???
    beq 2f
    ldr r3,[r2,#node_left]          @ load left node father
    cmp r3,r0                       @ equal current node ?
    streq r1,[r2,#node_left]        @ yes store left children
    strne r1,[r2,#node_right]       @ no store right
2:
    str r2,[r1,#node_parent]        @ change parent
    str r1,[r0,#node_parent]
    ldr r3,[r1,#node_right]
    str r3,[r0,#node_left]
    cmp r3,#0
    strne r0,[r3,#node_parent]      @ change parent node left
    str r0,[r1,#node_right]

    ldr r3,[r0,#node_left]          @ compute newbalance factor
    cmp r3,#0
    moveq r4,#0
    ldrne r4,[r3,#node_height]
    ldr r3,[r0,#node_right]
    cmp r3,#0
    moveq r5,#0
    ldrne r5,[r3,#node_height]
    cmp r4,r5
    addgt r4,#1
    strgt r4,[r0,#node_height]
    addle r5,#1
    strle r5,[r0,#node_height]
//
    ldr r3,[r1,#node_left]         @ compute new balance factor
    cmp r3,#0
    moveq r4,#0
    ldrne r4,[r3,#node_height]
    ldr r3,[r1,#node_right]
    cmp r3,#0
    moveq r5,#0
    ldrne r5,[r3,#node_height]
    cmp r4,r5
    addgt r4,#1
    strgt r4,[r1,#node_height]
    addle r5,#1
    strle r5,[r1,#node_height]
100:
    pop {r1-r5,lr}                   @ restaur registers
    bx lr
/******************************************************************/
/*     left rotation                                     */
/******************************************************************/
/* r0 contains the address of the node  sommet     */
rotLeft:                             @ INFO: rotLeft
    push {r1-r5,lr}                  @ save  registers
    //   r2                  r2
    //      r0                   r1
    //          r1            r0
    //        r3                 r3
    ldr r1,[r0,#node_right]          @ load right children
    ldr r2,[r0,#node_parent]         @ load father (racine)
    cmp r2,#0                        @ no father ???
    beq 2f
    ldr r3,[r2,#node_left]           @ load left node father
    cmp r3,r0                        @ equal current node ?
    streq r1,[r2,#node_left]         @ yes store left children
    strne r1,[r2,#node_right]        @ no store to right
2:
    str r2,[r1,#node_parent]         @ change parent of right children
    str r1,[r0,#node_parent]         @ change parent of sommet
    ldr r3,[r1,#node_left]           @ left children
    str r3,[r0,#node_right]          @ left children pivot exists ?
    cmp r3,#0
    strne r0,[r3,#node_parent]       @ yes store in
    str r0,[r1,#node_left]
//
    ldr r3,[r0,#node_left]           @ compute new height for old summit
    cmp r3,#0
    moveq r4,#0
    ldrne r4,[r3,#node_height]       @ left height
    ldr r3,[r0,#node_right]
    cmp r3,#0
    moveq r5,#0
    ldrne r5,[r3,#node_height]       @ right height
    cmp r4,r5
    addgt r4,#1
    strgt r4,[r0,#node_height]       @ if right > left
    addle r5,#1
    strle r5,[r0,#node_height]       @ if left > right
//
    ldr r3,[r1,#node_left]           @ compute new height for new
    cmp r3,#0
    moveq r4,#0
    ldrne r4,[r3,#node_height]
    ldr r3,[r1,#node_right]
    cmp r3,#0
    moveq r5,#0
    ldrne r5,[r3,#node_height]
    cmp r4,r5
    addgt r4,#1
    strgt r4,[r1,#node_height]
    addle r5,#1
    strle r5,[r1,#node_height]
100:
    pop {r1-r5,lr}                        @ restaur registers
    bx lr
/******************************************************************/
/*     search value in tree                                       */
/******************************************************************/
/* r0 contains the address of structure of tree */
/* r1 contains the value to search  */
searchTree:                           @ INFO: searchTree
    push {r1-r4,lr}                   @ save  registers
    ldr r2,[r0,#tree_root]

1:                                    @ begin loop
    ldr r4,[r2,#node_value]           @ load key
    cmp r1,r4
    beq 3f                            @ key equal
    blt 2f                            @ key <
                                      @ key >  insertion right
    ldr r3,[r2,#node_right]           @ node empty ?
    cmp r3,#0
    movne r2,r3                       @ no -> next node
    bne 1b                            @ and loop
    mov r0,#-1                        @ not find
    b 100f
2:                                    @ left
    ldr r3,[r2,#node_left]            @ left pointer empty ?
    cmp r3,#0
    movne r2,r3                       @
    bne 1b                            @ no -> loop
    mov r0,#-1                        @ not find
    b 100f
3:
    mov r0,r2                         @ return node address
100:
    pop {r1-r4,lr}                    @ restaur registers
    bx lr
/******************************************************************/
/*     suppression node                                           */
/******************************************************************/
/* r0 contains the address of the node */
/* r1 contains structure tree address  */
supprimer:                       @ INFO: supprimer
    push {r1-r8,lr}              @ save  registers
    ldr r1,[r0,#node_left]
    cmp r1,#0
    bne 5f
    ldr r1,[r0,#node_right]
    cmp r1,#0
    bne 5f
                                 @ is a leaf
    mov r4,#0
    ldr r3,[r0,#node_parent]     @ father
    cmp r3,#0
    streq r4,[r1,#tree_root]
    beq 100f
    ldr r1,[r3,#node_left]
    cmp r1,r0
    bne 2f
    str r4,[r3,#node_left]       @ suppression left children
    ldr r5,[r3,#node_right]
    cmp r5,#0
    moveq r6,#0
    ldrne r6,[r5,#node_height]
    add r6,#1
    str r6,[r3,#node_height]
    b 3f
2:                                @ suppression right children
    str r4,[r3,#node_right]
    ldr r5,[r3,#node_left]
    cmp r5,#0
    moveq r6,#0
    ldrne r6,[r5,#node_height]
    add r6,#1
    str r6,[r3,#node_height]
3:                                @ new balance
    mov r0,r3
    bl equilibrerSupp
    b 100f
5:                                @ is not à leaf
    ldr r7,[r0,#node_right]
    cmp r7,#0
    beq 7f
    mov r8,r0
    mov r0,r7
6:
    ldr r6,[r0,#node_left]
    cmp r6,#0
    movne r0,r6
    bne 6b
    b 9f
7:
    ldr r7,[r0,#node_left]         @ search the litle element
    cmp r7,#0
    beq 9f
    mov r8,r0
    mov r0,r7
8:
    ldr r6,[r0,#node_right]        @ search the great element
    cmp r6,#0
    movne r0,r6
    bne 8b
9:
    ldr r5,[r0,#node_value]         @ copy value
    str r5,[r8,#node_value]
    bl supprimer                    @ suppression node r0
100:
    pop {r1-r8,lr}                  @ restaur registers
    bx lr

/******************************************************************/
/*     equilibrer after suppression                                   */
/******************************************************************/
/* r0 contains the address of the node       */
/* r1 contains the address of head */
equilibrerSupp:                   @ INFO: equilibrerSupp
    push {r1-r8,lr}               @ save  registers
    mov r3,#1                     @ balance factor
    ldr r2,[r1,#tree_root]
1:
    ldr r5,[r0,#node_parent]      @ load father
    cmp r5,#0                     @ no father
    beq 100f
    cmp r3,#0                     @ balance equilibred
    beq 100f
    mov r6,r0                     @ save entry node
    ldr r0,[r6,#node_parent]      @ current = father
    ldr r7,[r0,#node_left]
    cmp r7,#0
    ldrne r8,[r7,#node_height]    @ height left tree
    moveq r8,#0
    ldr r7,[r0,#node_right]
    cmp r7,#0
    ldrne r9,[r7,#node_height]    @ height right tree
    moveq r9,#0
    cmp r8,r9
    addgt r8,#1
    strgt r8,[r0,#node_height]
    addle r9,#1
    strle r9,[r0,#node_height]
    //
    ldr r7,[r0,#node_right]
    cmp r7,#0
    ldrne r8,[r7,#node_height]
    moveq r8,#0
    ldr r7,[r0,#node_left]
    cmp r7,#0
    ldrne r9,[r7,#node_height]
    moveq r9,#0
    sub r3,r8,r9                   @ compute balance factor
    mov r2,r1
    mov r4,r0                      @ save current
    mov r1,r6
    bl equiUnSommet
                                   @ change head address ?
    cmp r2,r4
    streq r6,[r3,#tree_root]
    mov r0,r4                      @ restaur current
    b 1b

100:
    pop {r1-r8,lr}                  @ restaur registers
    bx lr                           @ return
/******************************************************************/
/*     preOrder                                  */
/******************************************************************/
/* r0 contains the address of the node */
/* r1 function address                 */
preOrder:                                 @ INFO: preOrder
    push {r1-r2,lr}                       @ save  registers
    cmp r0,#0
    beq 100f
    mov r2,r0
    blx r1                                @ call function

    ldr r0,[r2,#node_left]
    bl preOrder
    ldr r0,[r2,#node_right]
    bl preOrder
100:
    pop {r1-r2,lr}                        @ restaur registers
    bx lr

/******************************************************************/
/*     display node                                               */
/******************************************************************/
/* r0 contains node  address          */
displayElement:                        @ INFO: displayElement
    push {r1,r2,r3,lr}                 @ save  registers
    mov r2,r0
    ldr r1,iAdrsZoneConv
    bl conversion16
    mov r4,#0
    strb r4,[r1,r0]
    ldr r0,iAdrszMessResult
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#node_left]
    ldr r1,iAdrsZoneConv
    bl conversion16
    mov r4,#0
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#node_right]
    ldr r1,iAdrsZoneConv
    bl conversion16
    mov r4,#0
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#node_value]
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r4,#0
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#node_height]
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r4,#0
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#node_parent]
    ldr r1,iAdrsZoneConv
    bl conversion16
    mov r4,#0
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    bl affichageMess
100:
    pop {r1,r2,r3,lr}                        @ restaur registers
    bx lr                              @ return
iAdrszMessResult:          .int szMessResult
iAdrsZoneConv:             .int sZoneConv
iAdrsValue:                .int sValue

/******************************************************************/
/*     memory allocation on the heap                                  */
/******************************************************************/
/* r0 contains the size to allocate */
/* r0 returns address of memory heap or - 1 if error */
/* CAUTION : The size of the allowance must be a multiple of 4  */
allocHeap:
    push {r5-r7,lr}                   @ save  registers
    @ allocation
    mov r6,r0                         @ save size
    mov r0,#0                         @ read address start heap
    mov r7,#0x2D                      @ call system 'brk'
    svc #0
    mov r5,r0                         @ save address heap for return
    add r0,r6                         @ reservation place for size
    mov r7,#0x2D                      @ call system 'brk'
    svc #0
    cmp r0,#-1                        @ allocation error
    movne r0,r5                       @ return address memory heap
    pop {r5-r7,lr}                    @ restaur registers
    bx lr                             @ return
/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"

implement an AVL tree, a self-balancing binary search tree where the heights of the two child subtrees of any node differ by at most one. The code ensures this by rebalancing the tree after each insertion or deletion. The operations of lookup, insertion, and deletion all take O(log n) time. The code does not allow duplicate node keys. The AVL tree implemented can be compared with red-black trees for its efficiency in lookup-intensive applications.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program loopbreak.s   */

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessEndLoop: .asciz "loop break with value : \n"
szMessResult:  .ascii "Resultat = "      @ message result
sMessValeur:   .fill 12, 1, ' '
                   .asciz "\n"
.align 4
iGraine:  .int 123456
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                @ entry of program
    push {fp,lr}      @ saves 2 registers
1:    @ begin loop
    mov r4,#20
2:
    mov r0,#19
    bl genereraleas               @ generate number
    cmp r0,#10                       @ compar value
    beq 3f                         @ break if equal
    ldr r1,iAdrsMessValeur     @ display value
    bl conversion10             @ call function with 2 parameter (r0,r1)
    ldr r0,iAdrszMessResult
    bl affichageMess            @ display message
    subs r4,#1                   @ decrement counter
    bgt 2b                      @ loop if greather
    b 1b                          @ begin loop one

3:
    mov r2,r0             @ save value
    ldr r0,iAdrszMessEndLoop
    bl affichageMess            @ display message
    mov r0,r2
    ldr r1,iAdrsMessValeur
    bl conversion10       @ call function with 2 parameter (r0,r1)
    ldr r0,iAdrszMessResult
    bl affichageMess            @ display message

100:   @ standard end of the program
    mov r0, #0                  @ return code
    pop {fp,lr}                 @restaur 2 registers
    mov r7, #EXIT              @ request to exit program
    svc #0                       @ perform the system call

iAdrsMessValeur:          .int sMessValeur
iAdrszMessResult:         .int szMessResult
iAdrszMessEndLoop:        .int szMessEndLoop
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}      @ save  registres
    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 systeme
    pop {r0,r1,r2,r7,lr}        @ restaur des  2 registres */
    bx lr                       @ return
/******************************************************************/
/*     Converting a register to a decimal                                 */
/******************************************************************/
/* r0 contains value and r1 address area   */
conversion10:
    push {r1-r4,lr}    @ save registers
    mov r3,r1
    mov r2,#10

1:	   @ start loop
    bl divisionpar10 @ r0 <- dividende. quotient ->r0 reste -> r1
    add r1,#48        @ digit
    strb r1,[r3,r2]  @ store digit on area
    sub r2,#1         @ previous position
    cmp r0,#0         @ stop if quotient = 0 */
    bne 1b	          @ else loop
    @ and move spaces in first on area
    mov r1,#' '   @ space
2:
    strb r1,[r3,r2]  @ store space in area
    subs r2,#1       @ @ previous position
    bge 2b           @ loop if r2 >= zéro

100:
    pop {r1-r4,lr}    @ restaur registres
    bx lr	          @return
/***************************************************/
/*   division par 10   signé                       */
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/*
/* and   http://www.hackersdelight.org/            */
/***************************************************/
/* r0 dividende   */
/* r0 quotient */
/* r1 remainder  */
divisionpar10:
  /* r0 contains the argument to be divided by 10 */
    push {r2-r4}   /* save registers  */
    mov r4,r0
    mov r3,#0x6667   @ r3 <- magic_number  lower
    movt r3,#0x6666  @ r3 <- magic_number  upper
    smull r1, r2, r3, r0   @ r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0)
    mov r2, r2, ASR #2     /* r2 <- r2 >> 2 */
    mov r1, r0, LSR #31    /* r1 <- r0 >> 31 */
    add r0, r2, r1         /* r0 <- r2 + r1 */
    add r2,r0,r0, lsl #2   /* r2 <- r0 * 5 */
    sub r1,r4,r2, lsl #1   /* r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10) */
    pop {r2-r4}
    bx lr                  /* leave function */

/***************************************************/
/*   Generation random number                  */
/***************************************************/
/* r0 contains limit  */
genereraleas:
    push {r1-r4,lr}    @ save registers
    ldr r4,iAdriGraine
    ldr r2,[r4]
    ldr r3,iNbDep1
    mul r2,r3,r2
    ldr r3,iNbDep1
    add r2,r2,r3
    str r2,[r4]     @ maj de la graine pour l appel suivant

    mov r1,r0        @ divisor
    mov r0,r2        @ dividende
    bl division
    mov r0,r3       @  résult = remainder

100:                @ end function
    pop {r1-r4,lr}   @ restaur registers
    bx lr            @ return
/********************************************************************/
iAdriGraine: .int iGraine
iNbDep1: .int 0x343FD
iNbDep2: .int 0x269EC3
/***************************************************/
/* integer division unsigned                       */
/***************************************************/
division:
    /* r0 contains dividend */
    /* r1 contains divisor */
    /* r2 returns quotient */
    /* r3 returns remainder */
    push {r4, lr}
    mov r2, #0                @ init quotient
    mov r3, #0                @ init remainder
    mov r4, #32               @ init counter bits
    b 2f
1:          @ loop
    movs r0, r0, LSL #1     @ r0 <- r0 << 1 updating cpsr (sets C if 31st bit of r0 was 1)
    adc r3, r3, r3           @ r3 <- r3 + r3 + C. This is equivalent to r3 <- (r3 << 1) + C
    cmp r3, r1               @ compute r3 - r1 and update cpsr
    subhs r3, r3, r1        @ if r3 >= r1 (C=1) then r3 <- r3 - r1
    adc r2, r2, r2           @ r2 <- r2 + r2 + C. This is equivalent to r2 <- (r2 << 1) + C
2:
    subs r4, r4, #1          @ r4 <- r4 - 1
    bpl 1b                  @ if r4 >= 0 (N=0) then loop
    pop {r4, lr}
    bx lr

generate and print random numbers from 0 to 19. If the generated number is 10, the loop stops. If the number is not 10, a second random number is generated and printed before the loop restarts. If 10 is never generated, the loop runs indefinitely.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program xpathXml.s   */

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall

.equ NBMAXELEMENTS,    100

/*******************************************/
/* Structures                               */
/********************************************/
/* structure xmlNode*/
    .struct  0
xmlNode_private:                         @ application data
    .struct  xmlNode_private + 4
xmlNode_type:                            @ type number, must be second !
    .struct  xmlNode_type + 4
xmlNode_name:                            @ the name of the node, or the entity
    .struct  xmlNode_name + 4
xmlNode_children:                        @ parent->childs link
    .struct  xmlNode_children + 4
xmlNode_last:                            @ last child link
    .struct  xmlNode_last + 4
xmlNode_parent:                          @ child->parent link
    .struct  xmlNode_parent + 4
xmlNode_next:                            @ next sibling link
    .struct  xmlNode_next + 4
xmlNode_prev:                            @ previous sibling link
    .struct  xmlNode_prev + 4
xmlNode_doc:                             @ the containing document
    .struct  xmlNode_doc + 4
xmlNode_ns:                              @ pointer to the associated namespace
    .struct  xmlNode_ns + 4
xmlNode_content:                         @ the content
    .struct  xmlNode_content + 4
xmlNode_properties:                      @ properties list
    .struct  xmlNode_properties + 4
xmlNode_nsDef:                           @ namespace definitions on this node
    .struct  xmlNode_nsDef + 4
xmlNode_psvi:                            @ for type/PSVI informations
    .struct  xmlNode_psvi + 4
xmlNode_line:                            @ line number
    .struct  xmlNode_line + 4
xmlNode_extra:                           @ extra data for XPath/XSLT
    .struct  xmlNode_extra + 4
xmlNode_fin:
/********************************************/
/* structure xmlNodeSet*/
    .struct  0
xmlNodeSet_nodeNr:                       @ number of nodes in the set
    .struct  xmlNodeSet_nodeNr + 4
xmlNodeSet_nodeMax:                      @ size of the array as allocated
    .struct  xmlNodeSet_nodeMax + 4
xmlNodeSet_nodeTab:                      @ array of nodes in no particular order
    .struct  xmlNodeSet_nodeTab + 4
xmlNodeSet_fin:
/********************************************/
/* structure xmlXPathObject*/
    .struct  0
xmlPathObj_type:                         @
    .struct  xmlPathObj_type + 4
xmlPathObj_nodesetval:                   @
    .struct  xmlPathObj_nodesetval + 4
xmlPathObj_boolval:                      @
    .struct  xmlPathObj_boolval + 4
xmlPathObj_floatval:                     @
    .struct  xmlPathObj_floatval + 4
xmlPathObj_stringval:                    @
    .struct  xmlPathObj_stringval + 4
xmlPathObj_user:                         @
    .struct  xmlPathObj_user + 4
xmlPathObj_index:                        @
    .struct  xmlPathObj_index + 4
xmlPathObj_user2:                        @
    .struct  xmlPathObj_user2 + 4
xmlPathObj_index2:                       @
    .struct  xmlPathObj_index2 + 4

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessEndpgm:      .asciz "\nNormal end of program.\n"
szMessDisVal:      .asciz "\nDisplay set values.\n"
szMessDisArea:     .asciz "\nDisplay area values.\n"
szFileName:        .asciz "testXml.xml"
szMessError:       .asciz "Error detected !!!!. \n"

szLibName:         .asciz "name"
szLibPrice:        .asciz "//price"
szLibExtName:      .asciz "//name"
szCarriageReturn:  .asciz "\n"

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
tbExtract:          .skip 4 * NBMAXELEMENTS      @ result extract area
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                     @ entry of program
    ldr r0,iAdrszFileName
    bl xmlParseFile                       @ create doc
    mov r9,r0                             @ doc address
    mov r0,r9                             @ doc
    bl xmlDocGetRootElement               @ get root
    bl xmlFirstElementChild               @ get first section
    bl xmlFirstElementChild               @ get first item
    bl xmlFirstElementChild               @ get first name
    bl xmlNodeGetContent                  @ extract content
    bl affichageMess                      @ for display
    ldr r0,iAdrszCarriageReturn
    bl affichageMess

    ldr r0,iAdrszMessDisVal
    bl affichageMess
    mov r0,r9
    ldr r1,iAdrszLibPrice                  @ extract prices
    bl extractValue
    mov r0,r9
    ldr r1,iAdrszLibExtName                @ extact names
    bl extractValue
    ldr r0,iAdrszMessDisArea
    bl affichageMess
    mov r4,#0                              @ display string result area
    ldr r5,iAdrtbExtract
1:
    ldr r0,[r5,r4,lsl #2]
    cmp r0,#0
    beq 2f
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    add r4,#1
    b 1b

2:
    mov r0,r9
    bl xmlFreeDoc
    bl xmlCleanupParser
    ldr r0,iAdrszMessEndpgm
    bl affichageMess
    b 100f
99:
    @ error
    ldr r0,iAdrszMessError
    bl affichageMess
100:                                       @ standard end of the program
    mov r0, #0                             @ return code
    mov r7, #EXIT                          @ request to exit program
    svc #0                                 @ perform the system call

iAdrszMessError:          .int szMessError
iAdrszMessEndpgm:         .int szMessEndpgm
iAdrszLibName:            .int szLibName
iAdrszLibPrice:           .int szLibPrice
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrszFileName:           .int szFileName
iAdrszLibExtName:         .int szLibExtName
iAdrtbExtract:            .int tbExtract
iAdrszMessDisVal:          .int szMessDisVal
iAdrszMessDisArea:         .int szMessDisArea
/******************************************************************/
/*     extract value of set                                       */
/******************************************************************/
/* r0 contains the doc address
/* r1 contains the address of the libel to extract */
extractValue:
    push {r1-r10,lr}                     @ save  registres
    mov r4,r1                            @ save address libel
    mov r9,r0                            @ save doc
    ldr r8,iAdrtbExtract
    bl xmlXPathNewContext                @ create context
    mov r10,r0
    mov r1,r0
    mov r0,r4
    bl xmlXPathEvalExpression
    mov r5,r0
    mov r0,r10
    bl xmlXPathFreeContext               @ free context
    cmp r5,#0
    beq 100f
    ldr r4,[r5,#xmlPathObj_nodesetval]   @ values set
    ldr r6,[r4,#xmlNodeSet_nodeNr]       @ set size
    mov r7,#0                            @ index
    ldr r4,[r4,#xmlNodeSet_nodeTab]      @ area of nods
1:                                       @ start loop
    ldr r3,[r4,r7,lsl #2]                @ load node
    mov r0,r9
    ldr r1,[r3,#xmlNode_children]        @ load string value
    mov r2,#1
    bl xmlNodeListGetString
    str r0,[r8,r7,lsl #2]                @ store string pointer in area
    bl affichageMess                     @ and display string result
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    add r7,#1
    cmp r7,r6
    blt 1b
100:
    pop {r1-r10,lr}                      @ restaur registers */
    bx lr                                @ return

/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                   @ save  registres
    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 systeme
    pop {r0,r1,r2,r7,lr}                    @ restaur registers */
    bx lr                                   @ return

1. Retrieves the first "item" element from the XML document.
2. Prints out each "price" element from the XML document.
3. Gets an array of all the "name" elements from the XML document.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program quickSort.s   */
/* look pseudo code in wikipedia  quicksort */

/************************************/
/* Constantes                       */
/************************************/
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessSortOk:       .asciz "Table sorted.\n"
szMessSortNok:      .asciz "Table not sorted !!!!!.\n"
sMessResult:        .ascii "Value  : "
sMessValeur:        .fill 11, 1, ' '            @ size => 11
szCarriageReturn:   .asciz "\n"

.align 4
iGraine:  .int 123456
.equ NBELEMENTS,      10
#TableNumber:	     .int   9,5,6,1,2,3,10,8,4,7
#TableNumber:	     .int   1,3,5,2,4,6,10,8,4,7
#TableNumber:	     .int   1,3,5,2,4,6,10,8,4,7
#TableNumber:	     .int   1,2,3,4,5,6,10,8,4,7
TableNumber:	     .int   10,9,8,7,6,5,4,3,2,1
#TableNumber:	     .int   13,12,11,10,9,8,7,6,5,4,3,2,1
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                              @ entry of program

1:
    ldr r0,iAdrTableNumber                         @ address number table

    mov r1,#0                                      @ indice first item
    mov r2,#NBELEMENTS                             @ number of élements
    bl triRapide                                   @ call quicksort
    ldr r0,iAdrTableNumber                         @ address number table
    bl displayTable

    ldr r0,iAdrTableNumber                         @ address number table
    mov r1,#NBELEMENTS                             @ number of élements
    bl isSorted                                    @ control sort
    cmp r0,#1                                      @ sorted ?
    beq 2f
    ldr r0,iAdrszMessSortNok                       @ no !! error sort
    bl affichageMess
    b 100f
2:                                                 @ yes
    ldr r0,iAdrszMessSortOk
    bl affichageMess
100:                                               @ standard end of the program
    mov r0, #0                                     @ return code
    mov r7, #EXIT                                  @ request to exit program
    svc #0                                         @ perform the system call

iAdrsMessValeur:          .int sMessValeur
iAdrszCarriageReturn:    .int szCarriageReturn
iAdrsMessResult:          .int sMessResult
iAdrTableNumber:          .int TableNumber
iAdrszMessSortOk:         .int szMessSortOk
iAdrszMessSortNok:        .int szMessSortNok
/******************************************************************/
/*     control sorted table                                   */
/******************************************************************/
/* r0 contains the address of table */
/* r1 contains the number of elements  > 0  */
/* r0 return 0  if not sorted   1  if sorted */
isSorted:
    push {r2-r4,lr}                                    @ save registers
    mov r2,#0
    ldr r4,[r0,r2,lsl #2]
1:
    add r2,#1
    cmp r2,r1
    movge r0,#1
    bge 100f
    ldr r3,[r0,r2, lsl #2]
    cmp r3,r4
    movlt r0,#0
    blt 100f
    mov r4,r3
    b 1b
100:
    pop {r2-r4,lr}
    bx lr                                              @ return

/***************************************************/
/*   Appel récursif Tri Rapide quicksort           */
/***************************************************/
/* r0 contains the address of table */
/* r1 contains index of first item  */
/* r2 contains the number of elements  > 0  */
triRapide:
    push {r2-r5,lr}                                   @ save registers
    sub r2,#1                                         @ last item index
    cmp r1,r2                                         @ first > last ?
    bge 100f                                          @ yes -> end
    mov r4,r0                                         @ save r0
    mov r5,r2                                         @ save r2
    bl partition1                                     @ cutting into 2 parts
    mov r2,r0                                         @ index partition
    mov r0,r4                                         @ table address
    bl triRapide                                      @ sort lower part
    add r1,r2,#1                                      @ index begin = index partition + 1
    add r2,r5,#1                                      @ number of elements
    bl triRapide                                      @ sort higter part

 100:                                                 @ end function
    pop {r2-r5,lr}                                    @ restaur  registers
    bx lr                                             @ return

/******************************************************************/
/*      Partition table elements                                */
/******************************************************************/
/* r0 contains the address of table */
/* r1 contains index of first item  */
/* r2 contains index of last item   */

partition1:
    push {r1-r7,lr}                                    @ save registers
    ldr r3,[r0,r2,lsl #2]                              @ load value last index
    mov r4,r1                                          @ init with first index
    mov r5,r1                                          @ init with first index
1:                                                     @ begin loop
    ldr r6,[r0,r5,lsl #2]                              @ load value
    cmp r6,r3                                          @ compare value
    ldrlt r7,[r0,r4,lsl #2]                            @ if < swap value table
    strlt r6,[r0,r4,lsl #2]
    strlt r7,[r0,r5,lsl #2]
    addlt r4,#1                                        @ and increment index 1
    add    r5,#1                                       @ increment index 2
    cmp r5,r2                                          @ end ?
    blt 1b                                             @ no loop
    ldr r7,[r0,r4,lsl #2]                              @ swap value
    str r3,[r0,r4,lsl #2]
    str r7,[r0,r2,lsl #2]
    mov r0,r4                                          @ return index partition
100:
    pop {r1-r7,lr}
    bx lr

/******************************************************************/
/*      Display table elements                                */
/******************************************************************/
/* r0 contains the address of table */
displayTable:
    push {r0-r3,lr}                                    @ save registers
    mov r2,r0                                          @ table address
    mov r3,#0
1:                                                     @ loop display table
    ldr r0,[r2,r3,lsl #2]
    ldr r1,iAdrsMessValeur                             @ display value
    bl conversion10                                    @ call function
    ldr r0,iAdrsMessResult
    bl affichageMess                                   @ display message
    add r3,#1
    cmp r3,#NBELEMENTS - 1
    ble 1b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
100:
    pop {r0-r3,lr}
    bx lr
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                          @ save  registres
    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 systeme
    pop {r0,r1,r2,r7,lr}                           @ restaur des  2 registres */
    bx lr                                          @ return
/******************************************************************/
/*     Converting a register to a decimal unsigned                */
/******************************************************************/
/* r0 contains value and r1 address area   */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes          */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                                 @ save registers
    mov r3,r1
    mov r2,#LGZONECAL

1:	                                            @ start loop
    bl divisionpar10U                               @ unsigned  r0 <- dividende. quotient ->r0 reste -> r1
    add r1,#48                                      @ digit
    strb r1,[r3,r2]                                 @ store digit on area
    cmp r0,#0                                       @ stop if quotient = 0
    subne r2,#1                                     @ else previous position
    bne 1b	                                    @ and loop
                                                    @ and move digit from left of area
    mov r4,#0
2:
    ldrb r1,[r3,r2]
    strb r1,[r3,r4]
    add r2,#1
    add r4,#1
    cmp r2,#LGZONECAL
    ble 2b
                                                      @ and move spaces in end on area
    mov r0,r4                                         @ result length
    mov r1,#' '                                       @ space
3:
    strb r1,[r3,r4]                                   @ store space in area
    add r4,#1                                         @ next position
    cmp r4,#LGZONECAL
    ble 3b                                            @ loop if r4 <= area size

100:
    pop {r1-r4,lr}                                    @ restaur registres
    bx lr                                             @return

/***************************************************/
/*   division par 10   unsigned                    */
/***************************************************/
/* r0 dividende   */
/* r0 quotient */
/* r1 remainder  */
divisionpar10U:
    push {r2,r3,r4, lr}
    mov r4,r0                                          @ save value
    //mov r3,#0xCCCD                                   @ r3 <- magic_number lower  raspberry 3
    //movt r3,#0xCCCC                                  @ r3 <- magic_number higter raspberry 3
    ldr r3,iMagicNumber                                @ r3 <- magic_number    raspberry 1 2
    umull r1, r2, r3, r0                               @ r1<- Lower32Bits(r1*r0) r2<- Upper32Bits(r1*r0)
    mov r0, r2, LSR #3                                 @ r2 <- r2 >> shift 3
    add r2,r0,r0, lsl #2                               @ r2 <- r0 * 5
    sub r1,r4,r2, lsl #1                               @ r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10)
    pop {r2,r3,r4,lr}
    bx lr                                              @ leave function
iMagicNumber:  	.int 0xCCCCCCCD

implement the Quicksort algorithm to sort an array or list of elements. The algorithm works by choosing a pivot element and dividing the rest of the elements into two partitions - one with elements less than the pivot and the other with elements greater than the pivot. It then recursively sorts these partitions and joins them with the pivot to get the sorted array. The codes also include an optimized version of Quicksort that works in place by swapping elements within the array to avoid memory allocation of more arrays. The pivot selection method is not specified.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program dateFormat.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                              */
/*******************************************/
.equ STDOUT, 1           @ Linux output console
.equ EXIT,   1           @ Linux syscall
.equ WRITE,  4           @ Linux syscall
.equ BRK,    0x2d        @ Linux syscall
.equ CHARPOS,     '@'

.equ GETTIME,   0x4e     @ call system linux gettimeofday

/*******************************************/
/* Structures                               */
/********************************************/
/* example structure  time  */
    .struct  0
timeval_sec:                     @
    .struct  timeval_sec + 4
timeval_usec:                     @
    .struct  timeval_usec + 4
timeval_end:
    .struct  0
timezone_min:                     @
    .struct  timezone_min + 4
timezone_dsttime:                 @
    .struct  timezone_dsttime + 4
timezone_end:

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessError:       .asciz "Error detected !!!!. \n"
szMessResult:      .asciz "Date : @/@/@ \n"  @ message result
szMessResult1:     .asciz "Date day : @ @ @ @ \n"  @ message result
szJan:             .asciz "Janvier"
szFev:             .asciz "Février"
szMars:            .asciz "Mars"
szAvril:            .asciz "Avril"
szMai:             .asciz "Mai"
szJuin:            .asciz "Juin"
szJuil:            .asciz "Juillet"
szAout:            .asciz "Aout"
szSept:            .asciz "Septembre"
szOct:             .asciz "Octobre"
szNov:             .asciz "Novembre"
szDec:             .asciz "Décembre"
szLundi:           .asciz "Lundi"
szMardi:           .asciz "Mardi"
szMercredi:        .asciz "Mercredi"
szJeudi:           .asciz "Jeudi"
szVendredi:        .asciz "Vendredi"
szSamedi:          .asciz "Samedi"
szDimanche:        .asciz "Dimanche"
szCarriageReturn:  .asciz "\n"
.align 4
tbDayMonthYear:    .int  0,  31,  60,  91, 121, 152, 182, 213, 244, 274, 305, 335
                   .int 366, 397, 425, 456, 486, 517, 547, 578, 609, 639, 670, 700
                   .int 731, 762, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065
                   .int 1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430
tbMonthName:       .int szJan
                   .int szFev
                   .int szMars
                   .int szAvril
                   .int szMai
                   .int szJuin
                   .int szJuil
                   .int szAout
                   .int szSept
                   .int szOct
                   .int szNov
                   .int szDec
tbDayName:         .int szLundi
                   .int szMardi
                   .int szMercredi
                   .int szJeudi
                   .int szVendredi
                   .int szSamedi
                   .int szDimanche

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
stTVal:                .skip timeval_end
stTZone:               .skip timezone_end
sZoneConv:             .skip 100
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                              @ entry of program
    ldr r0,iAdrstTVal
    ldr r1,iAdrstTZone
    mov r7,#GETTIME
    svc 0
    cmp r0,#-1                     @ error ?
    beq 99f
    ldr r1,iAdrstTVal
    ldr r0,[r1,#timeval_sec]       @ timestemp in second
    bl dateFormatNum
    ldr r0,[r1,#timeval_sec]       @ timestemp in second
    bl dateFormatAlpha
    ldr r0,iTStest1
    bl dateFormatNum
    ldr r0,iTStest1
    bl dateFormatAlpha
    ldr r0,iTStest2
    bl dateFormatNum
    ldr r0,iTStest2
    bl dateFormatAlpha
    ldr r0,iTStest3
    bl dateFormatNum
    ldr r0,iTStest3
    bl dateFormatAlpha
    b 100f
99:
    ldr r0,iAdrszMessError
    bl affichageMess
100:                               @ standard end of the program
    mov r0,#0                      @ return code
    mov r7,#EXIT                   @ request to exit program
    svc 0                          @ perform the system call

iAdrszMessError:          .int szMessError
iAdrstTVal:               .int stTVal
iAdrstTZone:              .int stTZone
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrsZoneConv:            .int sZoneConv
iTStest1:                 .int 1609508339    @ 01/01/2021
iTStest2:                 .int 1657805939    @ 14/07/2022
iTStest3:                 .int 1767221999    @ 31/12/2025
/******************************************************************/
/*     date format numeric                                        */
/******************************************************************/
/* r0 contains the  timestamp in seconds */
dateFormatNum:
    push {r1-r11,lr}                             @ save  registers
    ldr r2,iSecJan2020
    sub r0,r0,r2                   @ total secondes to 01/01/2020
    mov r1,#60
    bl division
    mov r0,r2
    mov r6,r3                      @ compute secondes
    mov r1,#60
    bl division
    mov r7,r3                      @ compute minutes
    mov r0,r2
    mov r1,#24
    bl division
    mov r8,r3                      @ compute hours
    mov r0,r2
    mov r11,r0
    mov r1,#(365 * 4 + 1)
    bl division
    lsl r9,r2,#2                   @ multiply by 4 = year1
    mov r1,#(365 * 4 + 1)
    mov r0,r11
    bl division
    mov r10,r3

    ldr r1,iAdrtbDayMonthYear
    mov r2,#3
    mov r3,#12
1:
    mul r11,r3,r2
    ldr r4,[r1,r11,lsl #2]         @ load days by year
    cmp r10,r4
    bge 2f
    sub r2,r2,#1
    cmp r2,#0
    bne 1b
2:                                 @ r2 = year2
    mov r5,#11
    mul r11,r3,r2
    lsl r11,#2
    add r11,r1                     @ table address
3:
    ldr r4,[r11,r5,lsl #2]         @ load days by month
    cmp r10,r4
    bge 4f
    subs r5,r5,#1
    bne 3b
4:                                 @ r5 = month - 1
    mul r11,r3,r2
    add r11,r5
    ldr r1,iAdrtbDayMonthYear
    ldr r3,[r1,r11,lsl #2]
    sub r0,r10,r3
    add r0,r0,#1                   @ final compute day
    ldr r1,iAdrsZoneConv
    bl conversion10                @ this function do not zero final
    mov r11,#0                     @ store zero final
    strb r11,[r1,r0]
    ldr r0,iAdrszMessResult
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at first @ character
    mov r3,r0
    add r0,r5,#1                   @ final compute month
    cmp r0,#12
    subgt r0,#12
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r11,#0                      @ store zero final
    strb r11,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at next @ character
    mov r3,r0
    ldr r11,iYearStart
    add r0,r9,r11
    add r0,r0,r2                   @ final compute year = 2020 + year1 + year2
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r11,#0                     @ store zero final
    strb r11,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at next @ character
    bl affichageMess
100:
    pop {r1-r11,lr}                @ restaur registers
    bx lr                          @ return
iAdrszMessResult:         .int szMessResult
/******************************************************************/
/*     date format alphanumeric                                   */
/******************************************************************/
/* r0 contains the  timestamp in seconds */
dateFormatAlpha:
    push {r1-r10,lr}               @ save  registers
    ldr r2,iSecJan2020
    sub r0,r0,r2                   @ total secondes to 01/01/2020
    mov r6,r0
    mov r1,#60
    bl division
    mov r0,r2
    mov r1,#60
    bl division
    mov r0,r2
    mov r1,#24
    bl division
    mov r0,r2
    mov r8,r0
    mov r1,#(365 * 4 + 1)
    bl division
    lsl r9,r2,#2                   @ multiply by 4 = year1
    mov r1,#(365 * 4 + 1)
    mov r0,r8
    bl division
    mov r10,r3                     @ reste

    ldr r1,iAdrtbDayMonthYear
    mov r7,#3
    mov r3,#12
1:
    mul r8,r3,r7
    ldr r4,[r1,r8,lsl #2]          @ load days by year
    cmp r10,r4
    bge 2f
    sub r7,r7,#1
    cmp r7,#0
    bne 1b
2:                                 @ r7 = year2
    mov r5,#11
    mul r8,r3,r7
    lsl r8,#2
    add r8,r1
3:
    ldr r4,[r8,r5,lsl #2]          @ load days by month
    cmp r10,r4
    bge 4f
    subs r5,r5,#1
    bne 3b
4:                                 @ r5 = month - 1

    mov r0,r6                      @ number secondes depuis 01/01/2020
    ldr r1,iNbSecByDay
    bl division
    mov r0,r2
    mov r1,#7
    bl division
    add r2,r3,#2
    cmp r2,#7
    subge r2,#7
    ldr r1,iAdrtbDayName
    ldr r1,[r1,r2,lsl #2]
    ldr r0,iAdrszMessResult1
    bl strInsertAtCharInc          @ insert result at next @ character
    mov r3,r0
    mov r8,#12
    mul r11,r8,r7
    add r11,r5
    ldr r1,iAdrtbDayMonthYear
    ldr r8,[r1,r11,lsl #2]
    sub r0,r10,r8
    add r0,r0,#1                   @ final compute day
    ldr r1,iAdrsZoneConv
    bl conversion10                @ this function do not zero final
    mov r8,#0                      @ store zero final
    strb r8,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at first @ character
    mov r3,r0
    ldr r1,iAdrtbMonthName
    cmp r5,#12
    subge r5,#12
    ldr r1,[r1,r5,lsl #2]          @ month name
    mov r0,r3
    bl strInsertAtCharInc          @ insert result at first @ character
    mov r3,r0
    ldr r0,iYearStart
    add r0,r7
    add r0,r9                      @ final compute year = 2020 + year1 + year2

    ldr r1,iAdrsZoneConv
    bl conversion10                @ this function do not zero final
    mov r8,#0                      @ store zero final
    strb r8,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at first @ character
    bl affichageMess
100:
    pop {r1-r10,lr}                @ restaur registers
    bx lr                          @ return
iAdrszMessResult1:         .int szMessResult1
iSecJan2020:              .int 1577836800
iAdrtbDayMonthYear:       .int tbDayMonthYear
iYearStart:               .int 2020
iAdrtbMonthName:          .int tbMonthName
iAdrtbDayName:            .int tbDayName
iNbSecByDay:              .int 3600 * 24
/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"

display the current date in two formats: "2007-11-23" and "Friday, November 23, 2007".


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program areaString.s   */

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
/* Initialized data */
.data
szMessStringsch: .ascii "The string is at item : "
sZoneconv:		 .fill 12,1,' '
szCarriageReturn:  .asciz "\n"
szMessStringNfound: .asciz "The string is not found in this area.\n"

/* areas strings  */
szString1:  .asciz "Apples"
szString2:  .asciz "Oranges"
szString3:  .asciz "Pommes"
szString4:  .asciz "Raisins"
szString5:  .asciz "Abricots"

/* pointer items area 1*/
tablesPoi1:
pt1_1:	    .int szString1
pt1_2:	    .int szString2
pt1_3:	    .int szString3
pt1_4:	    .int szString4
ptVoid_1: .int 0
ptVoid_2: .int 0
ptVoid_3: .int 0
ptVoid_4: .int 0
ptVoid_5: .int 0

szStringSch:	.asciz "Raisins"
szStringSch1:	.asciz "Ananas"

/* UnInitialized data */
.bss

/*  code section */
.text
.global main
main:                /* entry of program  */
    push {fp,lr}    /* saves 2 registers */

    @@@@@@@@@@@@@@@@@@@@@@@@
    @ add string 5 to area
   @@@@@@@@@@@@@@@@@@@@@@@@
    ldr r1,iAdrtablesPoi1  @ begin pointer area 1
    mov r0,#0    @ counter
1:   @ search first void pointer
    ldr r2,[r1,r0,lsl #2]    @ read string pointer address item r0 (4 bytes by pointer)
    cmp r2,#0                @ is null ?
    addne r0,#1             @ no increment counter
    bne 1b                  @ and loop

    @ store pointer string 5 in area  at position r0
    ldr r2,iAdrszString5  @ address string 5
    str r2,[r1,r0,lsl #2]    @ store address

    @@@@@@@@@@@@@@@@@@@@@@@@
    @ display string at item 3
    @@@@@@@@@@@@@@@@@@@@@@@@
    mov r2,#2        @ pointers begin in position 0
    ldr r1,iAdrtablesPoi1  @ begin pointer area 1
    ldr r0,[r1,r2,lsl #2]
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess

    @@@@@@@@@@@@@@@@@@@@@@@@
    @ search string in area
    @@@@@@@@@@@@@@@@@@@@@@@@
    ldr r1,iAdrszStringSch
    //ldr r1,iAdrszStringSch1  @ uncomment for other search : not found !!
    ldr r2,iAdrtablesPoi1  @ begin pointer area 1
    mov r3,#0
2:   @ search
    ldr r0,[r2,r3,lsl #2]    @ read string pointer address item r0 (4 bytes by pointer)
    cmp r0,#0                @ is null ?
    beq 3f        @ end search
    bl comparaison
    cmp r0,#0                @ string = ?
    addne r3,#1             @ no increment counter
    bne 2b                  @ and loop
    mov r0,r3             @ position item string
    ldr r1,iAdrsZoneconv   @ conversion decimal
    bl conversion10S
    ldr r0,iAdrszMessStringsch
    bl affichageMess
    b 100f
3:   @ end search  string not found
    ldr r0,iAdrszMessStringNfound
    bl affichageMess

100:   /* standard end of the program */
    mov r0, #0                  @ return code
    pop {fp,lr}                 @restaur 2 registers
    mov r7, #EXIT              @ request to exit program
    swi 0                       @ perform the system call
iAdrtablesPoi1:		.int tablesPoi1
iAdrszMessStringsch:   .int szMessStringsch
iAdrszString5:		.int szString5
iAdrszStringSch:	.int szStringSch
iAdrszStringSch1:   .int szStringSch1
iAdrsZoneconv:       .int sZoneconv
iAdrszMessStringNfound:  .int szMessStringNfound
iAdrszCarriageReturn:  .int  szCarriageReturn
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {fp,lr}    			/* save  registres */
    push {r0,r1,r2,r7}    		/* save others 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" */
    swi #0                      /* call systeme */
    pop {r0,r1,r2,r7}     		/* restaur others registers */
    pop {fp,lr}    				/* restaur des  2 registres */
    bx lr	        			/* return  */
/***************************************************/
/*   conversion register signed décimal     */
/***************************************************/
/* r0 contient le registre   */
/* r1 contient l adresse de la zone de conversion */
conversion10S:
    push {r0-r5,lr}    /* save des registres */
    mov r2,r1       /* debut zone stockage */
    mov r5,#'+'     /* par defaut le signe est + */
    cmp r0,#0       /* nombre négatif ? */
    movlt r5,#'-'     /* oui le signe est - */
    mvnlt r0,r0       /* et inversion en valeur positive */
    addlt r0,#1
    mov r4,#10   /* longueur de la zone */
1: /* debut de boucle de conversion */
    bl divisionpar10 /* division  */
    add r1,#48        /* ajout de 48 au reste pour conversion ascii */
    strb r1,[r2,r4]  /* stockage du byte en début de zone r5 + la position r4 */
    sub r4,r4,#1      /* position précedente */
    cmp r0,#0
    bne 1b	       /* boucle si quotient different de zéro */
    strb r5,[r2,r4]  /* stockage du signe à la position courante */
    subs r4,r4,#1   /* position précedente */
    blt  100f         /* si r4 < 0  fin  */
    /* sinon il faut completer le debut de la zone avec des blancs */
    mov r3,#' '   /* caractere espace */
2:
    strb r3,[r2,r4]  /* stockage du byte  */
    subs r4,r4,#1   /* position précedente */
    bge 2b        /* boucle si r4 plus grand ou egal a zero */
100:  /* fin standard de la fonction  */
    pop {r0-r5,lr}   /*restaur desregistres */
    bx lr

/***************************************************/
/*   division par 10   signé                       */
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/*
/* and   http://www.hackersdelight.org/            */
/***************************************************/
/* r0 contient le dividende   */
/* r0 retourne le quotient */
/* r1 retourne le reste  */
divisionpar10:
  /* r0 contains the argument to be divided by 10 */
   push {r2-r4}   /* save registers  */
   mov r4,r0
   ldr r3, .Ls_magic_number_10 /* r1 <- magic_number */
   smull r1, r2, r3, r0   /* r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0) */
   mov r2, r2, ASR #2     /* r2 <- r2 >> 2 */
   mov r1, r0, LSR #31    /* r1 <- r0 >> 31 */
   add r0, r2, r1         /* r0 <- r2 + r1 */
   add r2,r0,r0, lsl #2   /* r2 <- r0 * 5 */
   sub r1,r4,r2, lsl #1   /* r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10) */
   pop {r2-r4}
   bx lr                  /* leave function */
   bx lr                  /* leave function */
.Ls_magic_number_10: .word 0x66666667

demonstrate the basic syntax of arrays in the specific programming language, including creating an array, assigning a value to it, and retrieving an element. It also showcases the use of both fixed-length and dynamic arrays, and includes the functionality of pushing a value into the array.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program readwrtfile.s   */

/*********************************************/
/*constantes                                */
/********************************************/
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ READ,   3
.equ WRITE,  4
.equ OPEN,   5
.equ CLOSE,  6
.equ CREATE,  8
/*  file */
.equ O_RDWR,	0x0002		@ open for reading and writing

.equ TAILLEBUF,  1000
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessErreur: .asciz "Erreur ouverture fichier input.\n"
szMessErreur4: .asciz "Erreur création fichier output.\n"
szMessErreur1: .asciz "Erreur fermeture fichier.\n"
szMessErreur2: .asciz "Erreur lecture fichier.\n"
szMessErreur3: .asciz "Erreur d'écriture dans fichier de sortie.\n"
szRetourligne: .asciz  "\n"
szMessErr: .ascii	"Error code : "
sDeci: .space 15,' '
         .asciz "\n"

szNameFileInput:	.asciz "input.txt"
szNameFile

demonstrate reading the contents of "input.txt" file into a variable and then writing this variable's contents into a new file called "output.txt".


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program loopnplusone.s   */

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessResult:      .ascii ""                    @ message result
sMessValeur:       .fill 11, 1, ' '
szMessComma:       .asciz ","
szCarriageReturn:  .asciz "\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                       @ entry of program
    mov r4,#1                               @ loop counter
1:                                          @ begin loop
    mov r0,r4
    ldr r1,iAdrsMessValeur                  @ display value
    bl conversion10                         @ decimal conversion
    ldr r0,iAdrszMessResult
    bl affichageMess                        @ display message
    ldr r0,iAdrszMessComma
    bl affichageMess                        @ display comma
    add r4,#1                               @ increment counter
    cmp r4,#10                              @ end ?
    blt 1b                                  @ no ->begin loop one
    mov r0,r4
    ldr r1,iAdrsMessValeur                  @ display value
    bl conversion10                         @ decimal conversion
    ldr r0,iAdrszMessResult
    bl affichageMess                        @ display message
    ldr r0,iAdrszCarriageReturn
    bl affichageMess                        @ display return line

100:                                        @ standard end of the program
    mov r0, #0                              @ return code
    mov r7, #EXIT                           @ request to exit program
    svc #0                                  @ perform the system call

iAdrsMessValeur:          .int sMessValeur
iAdrszMessResult:         .int szMessResult
iAdrszMessComma:          .int szMessComma
iAdrszCarriageReturn:     .int szCarriageReturn
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                   @ save  registres
    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 systeme
    pop {r0,r1,r2,r7,lr}                    @ restaur registers */
    bx lr                                   @ return
/******************************************************************/
/*     Converting a register to a decimal                                 */
/******************************************************************/
/* r0 contains value and r1 address area   */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                         @ save registers
    mov r3,r1
    mov r2,#LGZONECAL

1:                                          @ start loop
    bl divisionpar10                        @ r0 <- dividende. quotient ->r0 reste -> r1
    add r1,#48                              @ digit
    strb r1,[r3,r2]                         @ store digit on area
    sub r2,#1                               @ previous position
    cmp r0,#0                               @ stop if quotient = 0
    bne 1b                                  @ else loop
                                            @ end replaces digit in front of area
    mov r4,#0
2:
    ldrb r1,[r3,r2]
    strb r1,[r3,r4]                         @ store in area begin
    add r4,#1
    add r2,#1                               @ previous position
    cmp r2,#LGZONECAL                       @ end
    ble 2b                                  @ loop
    mov r1,#0                               @ final zero
    strb r1,[r3,r4]
100:
    pop {r1-r4,lr}                          @ restaur registres
    bx lr                                   @return
/***************************************************/
/*   division par 10   signé                       */
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/*
/* and   http://www.hackersdelight.org/            */
/***************************************************/
/* r0 dividende   */
/* r0 quotient */
/* r1 remainder  */
divisionpar10:
  /* r0 contains the argument to be divided by 10 */
    push {r2-r4}                           @ save registers  */
    mov r4,r0
    mov r3,#0x6667                         @ r3 <- magic_number  lower
    movt r3,#0x6666                        @ r3 <- magic_number  upper
    smull r1, r2, r3, r0                   @ r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0)
    mov r2, r2, ASR #2                     @ r2 <- r2 >> 2
    mov r1, r0, LSR #31                    @ r1 <- r0 >> 31
    add r0, r2, r1                         @ r0 <- r2 + r1
    add r2,r0,r0, lsl #2                   @ r2 <- r0 * 5
    sub r1,r4,r2, lsl #1                   @ r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10)
    pop {r2-r4}
    bx lr                                  @ return

The code writes a comma-separated list from 1 to 10, using separate output statements for the number and the comma within a loop. The loop executes a partial body in its last iteration.