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

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

/* Initialized data */
.data
szMessFound:             .asciz "String found. \n"
szMessNotFound:          .asciz "String not found. \n"
szString:                .asciz "abcdefghijklmnopqrstuvwxyz"
szString2:               .asciz "abc"
szStringStart:           .asciz "abcd"
szStringEnd:             .asciz "xyz"
szStringStart2:          .asciz "abcd"
szStringEnd2:            .asciz "xabc"
szCarriageReturn:        .asciz "\n"

/* UnInitialized data */
.bss

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

    ldr r0,iAdrszString                         @ address input string
    ldr r1,iAdrszStringStart                    @ address search string

    bl searchStringDeb                          @ Determining if the first string starts with second string
    cmp r0,#0
    ble 1f
    ldr r0,iAdrszMessFound                      @ display message
    bl affichageMess
    b 2f
1:
    ldr r0,iAdrszMessNotFound
    bl affichageMess
2:
    ldr r0,iAdrszString                         @ address input string
    ldr r1,iAdrszStringEnd                      @ address search string
    bl searchStringFin                          @ Determining if the first string ends with the second string
    cmp r0,#0
    ble 3f
    ldr r0,iAdrszMessFound                      @ display message
    bl affichageMess
    b 4f
3:
    ldr r0,iAdrszMessNotFound
    bl affichageMess
4:
    ldr r0,iAdrszString2                        @ address input string
    ldr r1,iAdrszStringStart2                   @ address search string

    bl searchStringDeb                          @
    cmp r0,#0
    ble 5f
    ldr r0,iAdrszMessFound                      @ display message
    bl affichageMess
    b 6f
5:
    ldr r0,iAdrszMessNotFound
    bl affichageMess
6:
    ldr r0,iAdrszString2                        @ address input string
    ldr r1,iAdrszStringEnd2                     @ address search string
    bl searchStringFin
    cmp r0,#0
    ble 7f
    ldr r0,iAdrszMessFound                      @ display message
    bl affichageMess
    b 8f
7:
    ldr r0,iAdrszMessNotFound
    bl affichageMess
8:
    ldr r0,iAdrszString                         @ address input string
    ldr r1,iAdrszStringEnd                      @ address search string
    bl searchSubString                          @ Determining if the first string contains the second string at any location
    cmp r0,#0
    ble 9f
    ldr r0,iAdrszMessFound                      @ display message
    bl affichageMess
    b 10f
9:
    ldr r0,iAdrszMessNotFound                   @ display substring result
    bl affichageMess
10:

100:                                            @ standard end of the program
    mov r0, #0                                  @ return code
    mov r7, #EXIT                               @ request to exit program
    svc 0                                       @ perform system call
iAdrszMessFound:          .int szMessFound
iAdrszMessNotFound:       .int szMessNotFound
iAdrszString:             .int szString
iAdrszString2:            .int szString2
iAdrszStringStart:        .int szStringStart
iAdrszStringEnd:          .int szStringEnd
iAdrszStringStart2:       .int szStringStart2
iAdrszStringEnd2:         .int szStringEnd2
iAdrszCarriageReturn:     .int szCarriageReturn
/******************************************************************/
/*     search substring at begin of input string                  */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of substring */
/* r0 returns 1 if find or 0 if not or -1 if error */
searchStringDeb:
    push {r1-r4,lr}                             @ save  registers
    mov r3,#0                                   @ counter byte  string
    ldrb r4,[r1,r3]                             @ load first byte of substring
    cmp r4,#0                                   @ empty string ?
    moveq r0,#-1                                @ error
    beq 100f
1:
    ldrb r2,[r0,r3]                             @ load byte string input
    cmp r2,#0                                   @ zero final ?
    moveq r0,#0                                 @ not find
    beq 100f
    cmp r4,r2                                   @ bytes equals ?
    movne r0,#0                                 @ no not find
    bne 100f
    add r3,#1                                   @ increment counter
    ldrb r4,[r1,r3]                             @ and load next byte of substring
    cmp r4,#0                                   @ zero final ?
    bne 1b                                      @ no -> loop
    mov r0,#1                                   @ yes is ok
100:
    pop {r1-r4,lr}                              @ restaur registers
    bx lr                                       @ return

/******************************************************************/
/*     search substring at end of input string                    */
/******************************************************************/
/* r0 contains the address of the input string */
/* r1 contains the address of substring */
/* r0 returns 1 if find or 0 if not or -1 if error */
searchStringFin:
    push {r1-r5,lr}                             @ save  registers
    mov r3,#0                                   @ counter byte  string
                                                @ search the last character of substring
1:
    ldrb r4,[r1,r3]                             @ load byte of substring
    cmp r4,#0                                   @ zero final ?
    addne r3,#1                                 @ no increment counter
    bne 1b                                      @ and loop
    cmp r3,#0                                   @ empty string ?
    moveq r0,#-1                                @ error
    beq 100f
    sub r3,#1                                   @ index of last byte
    ldrb r4,[r1,r3]                             @ load last byte of substring
                                                @ search the last character of string
    mov r2,#0                                   @ index last character
2:
    ldrb r5,[r0,r2]                             @ load first byte of substring
    cmp r5,#0                                   @ zero final ?
    addne r2,#1                                 @ no -> increment counter
    bne 2b                                      @ and loop
    cmp r2,#0                                   @ empty input string ?
    moveq r0,#0                                 @ yes -> not found
    beq 100f
    sub r2,#1                                   @ index last character
3:
    ldrb r5,[r0,r2]                             @ load byte string input
    cmp r4,r5                                   @ bytes equals ?
    movne r0,#0                                 @ no -> not found
    bne 100f
    subs r3,#1                                  @ decrement counter
    movlt r0,#1                                 @ if zero -> ok found
    blt 100f
    subs r2,#1                                  @ decrement counter input string
    movlt r0,#0                                 @ if zero -> not found
    blt 100f
    ldrb r4,[r1,r3]                             @ load previous byte of substring
    b 3b                                        @ and loop

100:
    pop {r1-r5,lr}                              @ restaur registers
    bx lr                                       @ return

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

The code checks if a given string starts with, contains, or ends with a second string. It also prints the location of the match and handles multiple occurrences of the second string within the first string.


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

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

.equ NBBOX,  7

/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessDeb:           .ascii "a="
sMessValeur_a:     .fill 11, 1, ' '            @ size => 11
                    .ascii "b="
sMessValeur_b:     .fill 11, 1, ' '            @ size => 11
                    .ascii "c="
sMessValeur_c:     .fill 11, 1, ' '            @ size => 11
                    .ascii "d="
sMessValeur_d:     .fill 11, 1, ' '            @ size => 11
                    .ascii "\n"
                    .ascii "e="
sMessValeur_e:     .fill 11, 1, ' '            @ size => 11
                    .ascii "f="
sMessValeur_f:     .fill 11, 1, ' '            @ size => 11
                    .ascii "g="
sMessValeur_g:     .fill 11, 1, ' '            @ size => 11

szCarriageReturn:   .asciz "\n************************\n"

sMessNbSolution:   .ascii "Number of solutions :"
sMessCounter:     .fill 11, 1, ' '            @ size => 11
                   .asciz "\n\n\n"

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
iValues_a:                .skip 4 * NBBOX
iValues_b:                .skip 4 * NBBOX - 1
iValues_c:                .skip 4 * NBBOX - 2
iValues_d:                .skip 4 * NBBOX - 3
iValues_e:                .skip 4 * NBBOX - 4
iValues_f:                .skip 4 * NBBOX - 5
iValues_g:                .skip 4 * NBBOX - 6
iCounterSol:              .skip 4
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                             @ entry of program
    mov r0,#1
    mov r1,#7
    mov r2,#3                                     @ 0 = rien 1 = display 2 = count 3 = les deux
    bl searchPb
    mov r0,#3
    mov r1,#9
    mov r2,#3                                     @ 0 = rien 1 = display 2 = count 3 = les deux
    bl searchPb
    mov r0,#0
    mov r1,#9
    mov r2,#2                                     @ 0 = rien 1 = display 2 = count 3 = les deux
    bl prepSearchNU

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

/******************************************************************/
/*     search problèm  value not unique                           */
/******************************************************************/
/* r0 contains start digit */
/* r1 contains end digit */
/* r2 contains action (0 display 1 count) */
prepSearchNU:
    push {r3-r12,lr}                              @ save  registers
    mov r5,#0                                     @ counter
    mov r12,r0                                    @ a
1:
    mov r11,r0                                    @ b
2:
    mov r10,r0                                    @ c
3:
    mov r9,r0                                     @ d
4:
    add r4,r12,r11                                @ a + b reference
    add r3,r11,r10
    add r3,r9                                     @ b + c + d
    cmp r4,r3
    bne 10f
    mov r8,r0                                     @ e
5:
    mov r7,r0                                     @ f
6:
    add r3,r9,r8
    add r3,r7                                     @ d + e + f
    cmp r3,r4
    bne 9f
    mov r6,r0                                     @ g
7:
    add r3,r7,r6                                  @ f + g
    cmp r3,r4
    bne 8f                                        @ not OK
                                                  @ OK
    add r5,#1                                     @ increment counter

8:
    add r6,#1                                     @ increment g
    cmp r6,r1
    ble 7b
9:
    add r7,#1                                     @ increment f
    cmp r7,r1
    ble 6b
    add r8,#1                                     @ increment e
    cmp r8,r1
    ble 5b
10:
    add r9,#1                                     @ increment d
    cmp r9,r1
    ble 4b
    add r10,#1                                    @ increment c
    cmp r10,r1
    ble 3b
    add r11,#1                                    @ increment b
    cmp r11,r1
    ble 2b
    add r12,#1                                    @ increment a
    cmp r12,r1
    ble 1b

    @ end
    tst r2,#0b10                                    @ print count ?
    beq 100f
    mov r0,r5                                       @ counter
    ldr r1,iAdrsMessCounter
    bl conversion10
    ldr r0,iAdrsMessNbSolution
    bl affichageMess

100:
    pop {r3-r12,lr}                                 @ restaur registers
    bx lr                                           @return
iAdrsMessCounter:                .int sMessCounter
iAdrsMessNbSolution:             .int sMessNbSolution

/******************************************************************/
/*     search problem  unique solution                            */
/******************************************************************/
/* r0 contains start digit */
/* r1 contains end digit */
/* r2 contains action (0 display 1 count) */
searchPb:
    push {r0-r12,lr}                                  @ save  registers
    @ init
    ldr r3,iAdriValues_a                              @ area value a
    mov r4,#0
1:                                                    @ loop init value a
    str r0,[r3,r4,lsl #2]
    add r4,#1
    add r0,#1
    cmp r0,r1
    ble 1b

    mov r5,#0                                         @ solution counter
    mov r12,#-1
2:
    add r12,#1                                        @ increment indice a
    cmp r12,#NBBOX-1
    bgt 90f
    ldr r0,iAdriValues_a                              @ area value a
    ldr r1,iAdriValues_b                              @ area value b
    mov r2,r12                                        @ indice  a
    mov r3,#NBBOX                                     @ number of origin values
    bl prepValues
    mov r11,#-1
3:
    add r11,#1                                        @ increment indice b
    cmp r11,#NBBOX - 2
    bgt 2b
    ldr r0,iAdriValues_b                              @ area value b
    ldr r1,iAdriValues_c                              @ area value c
    mov r2,r11                                        @ indice b
    mov r3,#NBBOX -1                                  @ number of origin values
    bl prepValues
    mov r10,#-1
4:
    add r10,#1
    cmp r10,#NBBOX - 3
    bgt 3b
    ldr r0,iAdriValues_c
    ldr r1,iAdriValues_d
    mov r2,r10
    mov r3,#NBBOX - 2
    bl prepValues
    mov r9,#-1
5:
    add r9,#1
    cmp r9,#NBBOX - 4
    bgt 4b
    @ control 2 firsts squares
    ldr r0,iAdriValues_a
    ldr r0,[r0,r12,lsl #2]
    ldr r1,iAdriValues_b
    ldr r1,[r1,r11,lsl #2]
    add r4,r0,r1                               @ a + b   value first square
    ldr r0,iAdriValues_c
    ldr r0,[r0,r10,lsl #2]
    add r7,r1,r0                               @ b + c
    ldr r1,iAdriValues_d
    ldr r1,[r1,r9,lsl #2]
    add r7,r1                                  @ b + c + d
    cmp r7,r4                                  @ equal first square ?
    bne 5b
    ldr r0,iAdriValues_d
    ldr r1,iAdriValues_e
    mov r2,r9
    mov r3,#NBBOX - 3
    bl prepValues
    mov r8,#-1
6:
    add r8,#1
    cmp r8,#NBBOX - 5
    bgt 5b
    ldr r0,iAdriValues_e
    ldr r1,iAdriValues_f
    mov r2,r8
    mov r3,#NBBOX - 4
    bl prepValues
    mov r7,#-1
7:
    add r7,#1
    cmp r7,#NBBOX - 6
    bgt 6b
    ldr r0,iAdriValues_d
    ldr r0,[r0,r9,lsl #2]
    ldr r1,iAdriValues_e
    ldr r1,[r1,r8,lsl #2]
    add r3,r0,r1                                @ d + e
    ldr r1,iAdriValues_f
    ldr r1,[r1,r7,lsl #2]
    add r3,r1                                   @ de + e + f
    cmp r3,r4                                   @ equal first square ?
    bne 7b
    ldr r0,iAdriValues_f
    ldr r1,iAdriValues_g
    mov r2,r7
    mov r3,#NBBOX - 5
    bl prepValues
    mov r6,#-1
8:
    add r6,#1
    cmp r6,#NBBOX - 7
    bgt 7b
    ldr r0,iAdriValues_f
    ldr r0,[r0,r7,lsl #2]
    ldr r1,iAdriValues_g
    ldr r1,[r1,r6,lsl #2]
    add r3,r0,r1                               @ f +g
    cmp r4,r3                                  @ equal first square ?
    bne 8b
    add r5,#1                                  @ increment counter
    ldr r0,[sp,#8]                             @ load action for two parameter in stack
    tst r0,#0b1
    beq 9f                                     @ display solution ?
    ldr r0,iAdriValues_a
    ldr r0,[r0,r12,lsl #2]
    ldr r1,iAdrsMessValeur_a
    bl conversion10
    ldr r0,iAdriValues_b
    ldr r0,[r0,r11,lsl #2]
    ldr r1,iAdrsMessValeur_b
    bl conversion10
    ldr r0,iAdriValues_c
    ldr r0,[r0,r10,lsl #2]
    ldr r1,iAdrsMessValeur_c
    bl conversion10
    ldr r0,iAdriValues_d
    ldr r0,[r0,r9,lsl #2]
    ldr r1,iAdrsMessValeur_d
    bl conversion10
    ldr r0,iAdriValues_e
    ldr r0,[r0,r8,lsl #2]
    ldr r1,iAdrsMessValeur_e
    bl conversion10
    ldr r0,iAdriValues_f
    ldr r0,[r0,r7,lsl #2]
    ldr r1,iAdrsMessValeur_f
    bl conversion10
    ldr r0,iAdriValues_g
    ldr r0,[r0,r6,lsl #2]
    ldr r1,iAdrsMessValeur_g
    bl conversion10
    ldr r0,iAdrsMessDeb
    bl affichageMess
9:
    b 8b    @ suite

90:
    ldr r0,[sp,#8]                                @ load action for two parameter in stack
    tst r0,#0b10
    beq 100f                                      @ display counter ?
    mov r0,r5
    ldr r1,iAdrsMessCounter
    bl conversion10
    ldr r0,iAdrsMessNbSolution
    bl affichageMess
100:
    pop {r0-r12,lr}                               @ restaur registers
    bx lr                                         @return
iAdriValues_a:                   .int iValues_a
iAdriValues_b:                   .int iValues_b
iAdriValues_c:                   .int iValues_c
iAdriValues_d:                   .int iValues_d
iAdriValues_e:                   .int iValues_e
iAdriValues_f:                   .int iValues_f
iAdriValues_g:                   .int iValues_g

iAdrsMessValeur_a:               .int sMessValeur_a
iAdrsMessValeur_b:               .int sMessValeur_b
iAdrsMessValeur_c:               .int sMessValeur_c
iAdrsMessValeur_d:               .int sMessValeur_d
iAdrsMessValeur_e:               .int sMessValeur_e
iAdrsMessValeur_f:               .int sMessValeur_f
iAdrsMessValeur_g:               .int sMessValeur_g
iAdrsMessDeb:                    .int sMessDeb
iAdriCounterSol:                 .int iCounterSol
/******************************************************************/
/*     copy value area  and substract value of indice             */
/******************************************************************/
/* r0 contains the address of values origin */
/* r1 contains the address of values destination */
/* r2 contains value indice to substract     */
/* r3 contains origin values number          */
prepValues:
    push {r1-r6,lr}                                @ save  registres
    mov r4,#0                                      @ indice origin value
    mov r5,#0                                      @ indice destination value
1:
    cmp r4,r2                                      @ substract indice ?
    beq 2f                                         @ yes -> jump
    ldr r6,[r0,r4,lsl #2]                          @ no -> copy value
    str r6,[r1,r5,lsl #2]
    add r5,#1                                      @ increment destination indice
2:
   add r4,#1                                       @ increment origin indice
   cmp r4,r3                                       @ end ?
   blt 1b
100:
    pop {r1-r6,lr}                                 @ restaur registres
    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 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
    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

The code finds all possible solutions for a 4-squares puzzle where each square sums up to the same total. It operates under two conditions: each letter representing a unique value between 1-7 and 3-9, and each letter representing a non-unique value between 0-9. The code also counts the number of non-unique solutions.


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

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

.equ NBELEMENTS,      100                @ list size

/*******************************************/
/* Structures                               */
/********************************************/
/* structure linkedlist*/
    .struct  0
llist_next:                             @ next element
    .struct  llist_next + 4
llist_value:                            @ element value
    .struct  llist_value + 4
llist_fin:
/* Initialized data */
.data
szMessInitListe:         .asciz "List initialized.\n"
szCarriageReturn:        .asciz "\n"
/* datas error display */
szMessErreur:            .asciz "Error detected.\n"

/* UnInitialized data */
.bss
lList1:                  .skip llist_fin * NBELEMENTS    @ list memory place

/*  code section */
.text
.global main
main:
    ldr r0,iAdrlList1
    mov r1,#0
    str r1,[r0,#llist_next]
    ldr r0,iAdrszMessInitListe
    bl affichageMess

100:                                    @ standard end of the program
    mov r7, #EXIT                       @ request to exit program
    svc 0                               @ perform system call
iAdrszMessInitListe:       .int szMessInitListe
iAdrszMessErreur:          .int szMessErreur
iAdrszCarriageReturn:      .int szCarriageReturn
iAdrlList1:                .int lList1
/******************************************************************/
/*     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

define a data structure for a singly-linked list element. This element contains a data member for storing a numeric value and a mutable link to the next element in the list.


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

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
/* Initialized data */
.data
szMessDeb: .ascii "Factors of :"
sMessValeur:   .fill 12, 1, ' '
                   .asciz "are : \n"
sMessFactor:   .fill 12, 1, ' '
                   .asciz "\n"
szCarriageReturn:  .asciz "\n"

/* UnInitialized data */
.bss

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

    mov r0,#100
    bl factors
    mov r0,#97
    bl factors
    ldr r0,iNumber
    bl factors

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

iNumber: .int 32767
iAdrszCarriageReturn:  .int  szCarriageReturn
/******************************************************************/
/*     calcul factors of number                                  */
/******************************************************************/
/* r0 contains the number */
factors:
    push {fp,lr}    			/* save  registres */
    push {r1-r6}    		/* save others registers */
    mov r5,r0    @ limit calcul
    ldr r1,iAdrsMessValeur   @ conversion register in decimal string
    bl conversion10S
    ldr r0,iAdrszMessDeb     @ display message
    bl affichageMess
    mov r6,#1    @ counter loop
1:   @ loop
    mov r0,r5    @ dividende
    mov r1,r6    @ divisor
    bl division
    cmp r3,#0    @ remainder = zero ?
    bne 2f
    @ display result if yes
    mov r0,r6
    ldr r1,iAdrsMessFactor
    bl conversion10S
    ldr r0,iAdrsMessFactor
    bl affichageMess
2:
    add r6,#1      @ add 1 to loop counter
    cmp r6,r5      @ <=  number ?
    ble 1b        @ yes loop
100:
    pop {r1-r6}     		/* restaur others registers */
    pop {fp,lr}    				/* restaur des  2 registres */
    bx lr	        			/* return  */
iAdrsMessValeur: .int sMessValeur
iAdrszMessDeb: .int szMessDeb
iAdrsMessFactor: .int sMessFactor
/******************************************************************/
/*     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  */
/*=============================================*/
/* division integer unsigned                */
/*============================================*/
division:
    /* r0 contains N */
    /* r1 contains D */
    /* r2 contains Q */
    /* r3 contains R */
    push {r4, lr}
    mov r2, #0                 /* r2 ? 0 */
    mov r3, #0                 /* r3 ? 0 */
    mov r4, #32                /* r4 ? 32 */
    b 2f
1:
    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 branch to .Lloop1 */

    pop {r4, lr}
    bx lr

/***************************************************/
/*   conversion register in string décimal signed  */
/***************************************************/
/* r0 contains the register   */
/* r1 contains address of conversion area */
conversion10S:
    push {fp,lr}    /* save registers frame and return */
    push {r0-r5}   /* save other registers  */
    mov r2,r1       /* early storage area */
    mov r5,#'+'     /* default sign is + */
    cmp r0,#0       /* négatif number ? */
    movlt r5,#'-'     /* yes sign is - */
    mvnlt r0,r0       /* and inverse in positive value */
    addlt r0,#1
    mov r4,#10   /* area length */
1: /* conversion loop */
    bl divisionpar10 /* division  */
    add r1,#48        /* add 48 at remainder for conversion ascii */
    strb r1,[r2,r4]  /* store byte area r5 + position r4 */
    sub r4,r4,#1      /* previous position */
    cmp r0,#0
    bne 1b	       /* loop if quotient not equal zéro */
    strb r5,[r2,r4]  /* store sign at current position  */
    subs r4,r4,#1   /* previous position */
    blt  100f         /* if r4 < 0  end  */
    /* else complete area with space */
    mov r3,#' '   /* character space */
2:
    strb r3,[r2,r4]  /* store  byte  */
    subs r4,r4,#1   /* previous position */
    bge 2b        /* loop if r4 greather or equal zero */
100:  /*  standard end of function  */
    pop {r0-r5}   /*restaur others registers */
    pop {fp,lr}   /* restaur des  2 registers frame et return  */
    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 autres registres  */
   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 */
   .align 4
.Ls_magic_number_10: .word 0x66666667

compute the factors of a given positive integer, excluding zero and negative numbers. The factors are the positive integers that can divide the input number to yield a positive integer. For prime numbers, the factors are 1 and the number itself.


Works with: as version Raspberry Pi  or android 32 bits with application Termux
/* ARM assembly Raspberry PI  */
/*  program alignColumn.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 */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"
.equ BUFFERSIZE, 20 * 10

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessLeft:        .asciz "LEFT :\n"
szMessRight:       .asciz "\nRIGHT :\n"
szMessCenter:      .asciz "\nCENTER :\n"
szCarriageReturn:  .asciz "\n"

szLine1:    .asciz "Given$a$text$file$of$many$lines,$where$fields$within$a$line$"
szLine2:    .asciz "are$delineated$by$a$single$'dollar'$character,$write$a$program"
szLine3:    .asciz "that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$"
szLine4:    .asciz "column$are$separated$by$at$least$one$space."
szLine5:    .asciz "Further,$allow$for$each$word$in$a$column$to$be$either$left$"
szLine6:    .asciz "justified,$right$justified,$or$center$justified$within$its$column."

itbPtLine:    .int szLine1,szLine2,szLine3,szLine4,szLine5,szLine6
              .equ NBLINES, (. - itbPtLine) / 4

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                               @ entry of program
    ldr r0,iAdritbPtLine
    bl computeMaxiLengthWords
    mov r10,r0                      @ column counter
    ldr r0,iAdrszMessLeft
    bl affichageMess
    ldr r0,iAdritbPtLine
    mov r1,r10                      @ column size
    bl alignLeft
    ldr r0,iAdrszMessRight
    bl affichageMess
    ldr r0,iAdritbPtLine
    mov r1,r10                      @ column size
    bl alignRight
    ldr r0,iAdrszMessCenter
    bl affichageMess
    ldr r0,iAdritbPtLine
    mov r1,r10                      @ column size
    bl alignCenter
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
iAdrszMessLeft:           .int szMessLeft
iAdrszMessRight:          .int szMessRight
iAdrszMessCenter:         .int szMessCenter
iAdritbPtLine:            .int itbPtLine
/******************************************************************/
/*      compute maxi words                                 */
/******************************************************************/
/* r0 contains adresse pointer array */
computeMaxiLengthWords:
    push {r1-r6,lr}          @ save registers
    mov r2,#0                @ indice pointer array
    mov r3,#0                @ maxi length words
1:
    ldr r1,[r0,r2,lsl #2]    @ load pointer
    mov r4,#0                @ length words counter
    mov r5,#0                @ indice line character
2:
    ldrb r6,[r1,r5]          @ load a line character
    cmp r6,#0                @ line end ?
    beq 4f
    cmp r6,#'$'              @ separator ?
    bne 3f
    cmp r4,r3
    movgt r3,r4              @ ig greather replace maxi
    mov r4,#-1               @ raz length counter
3:
    add r4,r4,#1
    add r5,r5,#1             @ increment character indice
    b 2b                     @ and loop
4:                           @ end line
    cmp r4,r3                @ compare word counter and maxi
    movgt r3,r4              @ if greather replace maxi
    add r2,r2,#1             @ increment indice line pointer
    cmp r2,#NBLINES          @ maxi ?
    blt 1b                   @ no -> loop

    mov r0,r3                @ return maxi length counter
100:
    pop {r1-r6,pc}

/******************************************************************/
/*      align left                                                */
/******************************************************************/
/* r0 contains the address of pointer array*/
/* r1 contains column size */
alignLeft:
    push {r4-r7,fp,lr}       @ save registers
    sub sp,sp,#BUFFERSIZE    @ reserve place for output buffer
    mov fp,sp
    mov r5,r0                @ array address
    mov r2,#0                @ indice array
1:
    ldr r3,[r5,r2,lsl #2]    @ load line pointer
    mov r4,#0                @ line character indice
    mov r7,#0                @ output buffer character indice
    mov r6,#0                @ word lenght
2:
    ldrb r0,[r3,r4]          @ load a character line
    strb r0,[fp,r7]          @ store in buffer
    cmp r0,#0                @ line end ?
    beq 6f
    cmp r0,#'$'              @ separator ?
    bne 5f
    mov r0,#' '
    strb r0,[fp,r7]          @ replace $ by space
3:
    cmp r6,r1                @ length word >= length column
    bge 4f
    add r7,r7,#1
    mov r0,#' '
    strb r0,[fp,r7]          @ add space to buffer
    add r6,r6,#1
    b 3b                     @ and loop
4:
    mov r6,#-1               @ raz word length
5:
    add r4,r4,#1             @ increment line indice
    add r7,r7,#1             @ increment buffer indice
    add r6,r6,#1             @ increment word length
    b 2b

6:
    mov r0,#'\n'
    strb r0,[fp,r7]          @ return line
    add r7,r7,#1
    mov r0,#0
    strb r0,[fp,r7]          @ final zéro
    mov r0,fp
    bl affichageMess         @ display output buffer
    add r2,r2,#1
    cmp r2,#NBLINES
    blt 1b

100:
    add sp,sp,#BUFFERSIZE
    pop {r4-r7,fp,pc}
/******************************************************************/
/*      align right                                                */
/******************************************************************/
/* r0 contains the address of pointer array*/
/* r1 contains column size */
alignRight:
    push {r4-r9,fp,lr}       @ save registers
    sub sp,sp,#BUFFERSIZE    @ reserve place for output buffer
    mov fp,sp
    mov r5,r0                @ array address
    mov r2,#0                @ indice array
1:
    ldr r3,[r5,r2,lsl #2]    @ load line pointer
    mov r4,#0                @ line character indice
    mov r7,#0                @ output buffer character indice
    mov r6,#0                @ word lenght
    mov r8,r3                @ word begin address
2:                           @ compute word length
    ldrb r0,[r3,r4]          @ load a character line
    cmp r0,#0                @ line end ?
    beq 3f
    cmp r0,#'$'              @ separator ?
    beq 3f
    add r4,r4,#1             @ increment line indice
    add r6,r6,#1             @ increment word length
    b 2b

3:
    cmp r6,#0
    beq 4f
    sub r6,r1,r6             @ compute left spaces to add
4:                           @ loop add spaces to buffer
    cmp r6,#0
    blt 5f
    mov r0,#' '
    strb r0,[fp,r7]          @ add space to buffer
    add r7,r7,#1
    sub r6,r6,#1
    b 4b                     @ and loop
5:
    mov r9,#0
6:                           @ copy loop word to buffer
    ldrb r0,[r8,r9]
    cmp r0,#'$'
    beq 7f
    cmp r0,#0                @ line end
    beq 8f
    strb r0,[fp,r7]
    add r7,r7,#1
    add r9,r9,#1
    b 6b
7:
    add r8,r8,r9
    add r8,r8,#1             @ new word begin
    mov r6,#0                @ raz word length
    add r4,r4,#1             @ increment line indice
    b 2b

8:
    mov r0,#'\n'
    strb r0,[fp,r7]          @ return line
    add r7,r7,#1
    mov r0,#0
    strb r0,[fp,r7]          @ final zéro
    mov r0,fp
    bl affichageMess         @ display output buffer
    add r2,r2,#1
    cmp r2,#NBLINES
    blt 1b

100:
    add sp,sp,#BUFFERSIZE
    pop {r4-r9,fp,pc}
/******************************************************************/
/*      align center                                                */
/******************************************************************/
/* r0 contains the address of pointer array*/
/* r1 contains column size */
alignCenter:
    push {r4-r12,lr}         @ save registers
    sub sp,sp,#BUFFERSIZE    @ reserve place for output buffer
    mov fp,sp
    mov r5,r0                @ array address
    mov r2,#0                @ indice array
1:
    ldr r3,[r5,r2,lsl #2]    @ load line pointer
    mov r4,#0                @ line character indice
    mov r7,#0                @ output buffer character indice
    mov r6,#0                @ word length
    mov r8,r3                @ word begin address
2:                           @ compute word length
    ldrb r0,[r3,r4]          @ load a character line
    cmp r0,#0                @ line end ?
    beq 3f
    cmp r0,#'$'              @ separator ?
    beq 3f
    add r4,r4,#1             @ increment line indice
    add r6,r6,#1             @ increment word length
    b 2b
3:
    cmp r6,#0
    beq 5f
    sub r6,r1,r6             @ total spaces number to add
    mov r12,r6
    lsr r6,r6,#1             @ divise by 2 = left spaces number
4:
    cmp r6,#0
    blt 5f
    mov r0,#' '
    strb r0,[fp,r7]          @ add space to buffer
    add r7,r7,#1             @ increment output indice
    sub r6,r6,#1             @ decrement number space
    b 4b                     @ and loop
5:
    mov r9,#0
6:                           @ copy loop word to buffer
    ldrb r0,[r8,r9]
    cmp r0,#'$'              @ séparator ?
    beq 7f
    cmp r0,#0                @ line end ?
    beq 10f
    strb r0,[fp,r7]
    add r7,r7,#1
    add r9,r9,#1
    b 6b
7:
    lsr r6,r12,#1            @ divise total spaces by 2
    sub r6,r12,r6            @ and compute number spaces to right side
8:                           @ loop to add right spaces
    cmp r6,#0
    ble 9f
    mov r0,#' '
    strb r0,[fp,r7]          @ add space to buffer
    add r7,r7,#1
    sub r6,r6,#1
    b 8b                     @ and loop

9:
    add r8,r8,r9
    add r8,r8,#1             @ new address word begin
    mov r6,#0                @ raz word length
    add r4,r4,#1             @ increment line indice
    b 2b                     @ and loop new word

10:
    mov r0,#'\n'
    strb r0,[fp,r7]          @ return line
    add r7,r7,#1
    mov r0,#0
    strb r0,[fp,r7]          @ final zéro
    mov r0,fp
    bl affichageMess         @ display output buffer
    add r2,r2,#1             @ increment line indice
    cmp r2,#NBLINES          @ maxi ?
    blt 1b                   @ loop

100:
    add sp,sp,#BUFFERSIZE
    pop {r4-r12,pc}
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
LEFT :
Given      a          text       file       of         many       lines,     where      fields     within     a          line
are        delineated by         a          single     'dollar'   character, write      a          program
that       aligns     each       column     of         fields     by         ensuring   that       words      in         each
column     are        separated  by         at         least      one        space.
Further,   allow      for        each       word       in         a          column     to         be         either     left
justified, right      justified, or         center     justified  within     its        column.

RIGHT :
      Given          a       text       file         of       many     lines,      where     fields     within          a       line
        are delineated         by          a     single   'dollar' character,      write          a    program
       that     aligns       each     column         of     fields         by   ensuring       that      words         in       each
     column        are  separated         by         at      least        one     space.
   Further,      allow        for       each       word         in          a     column         to         be     either       left
 justified,      right justified,         or     center  justified     within        its    column.

CENTER :
   Given        a         text       file        of        many      lines,     where      fields     within       a         line
    are     delineated     by         a        single    'dollar'  character,   write        a       program
    that      aligns      each      column       of       fields       by      ensuring     that      words        in        each
   column      are     separated      by         at       least       one       space.
  Further,    allow       for        each       word        in         a        column       to         be       either      left
 justified,   right    justified,     or       center   justified    within      its      column.

The code reads a text file with lines separated by a dollar character. It aligns each column of fields by ensuring at least one space between words in each column. It also allows each word in a column to be left, right, or center justified. The minimum space between columns is computed from the text, not hard-coded. Trailing dollar characters or consecutive spaces at the end of lines do not affect the alignment. The output is suitable for viewing in a mono-spaced font on a plain text editor or basic terminal.


Works with: as version Raspberry Pi  or android 32 bits with application Termux
/* ARM assembly Raspberry PI  */
/*  program rot13.s   */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

.equ STRINGSIZE,          500
/************************************/
/* Initialized data                 */
/************************************/
.data
szMessString:            .asciz "String :\n"
szMessEncrip:            .asciz "\nEncrypted :\n"
szMessDecrip:            .asciz "\nDecrypted :\n"
szString1:               .asciz "{NOWHERE! abcd xyz 1234}"

szCarriageReturn:       .asciz "\n"
/************************************/
/* UnInitialized data               */
/************************************/
.bss
szString2:                .skip  STRINGSIZE
szString3:                .skip  STRINGSIZE
/************************************/
/*  code section                    */
/************************************/
.text
.global main
main:

    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszString1                        @ display string
    bl affichageMess
    ldr r0,iAdrszString1
    ldr r1,iAdrszString2
    bl encryptRot13
    ldr r0,iAdrszMessEncrip
    bl affichageMess
    ldr r0,iAdrszString2                        @ display string
    bl affichageMess
    ldr r0,iAdrszString2
    ldr r1,iAdrszString3
    bl decryptRot13
    ldr r0,iAdrszMessDecrip
    bl affichageMess
    ldr r0,iAdrszString3                        @ display string
    bl affichageMess
    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 system call
iAdrszMessString:         .int szMessString
iAdrszMessDecrip:         .int szMessDecrip
iAdrszMessEncrip:         .int szMessEncrip
iAdrszString1:            .int szString1
iAdrszString2:            .int szString2
iAdrszString3:            .int szString3
iAdrszCarriageReturn:     .int szCarriageReturn
/******************************************************************/
/*     encrypt strings                         */
/******************************************************************/
/* r0 contains the address of the string1 */
/* r1 contains the address of the encrypted string */
encryptRot13:
    push {r3,r4,lr}           @ save  registers
    mov r3,#0                 @ counter byte string 1
    mov r2,#13                @ rot characters number
1:
    ldrb r4,[r0,r3]           @ load byte string 1
    cmp r4,#0                 @ zero final ?
    streqb r4,[r1,r3]
    moveq r0,r3
    beq 100f
    cmp r4,#65                @ < A ?
    strltb r4,[r1,r3]
    addlt r3,#1
    blt 1b
    cmp r4,#90                @ > Z
    bgt 2f
    add r4,r2                 @ add key
    cmp r4,#90                @ > Z
    subgt r4,#26
    strb r4,[r1,r3]
    add r3,#1
    b 1b
2:
    cmp r4,#97                @ < a ?
    strltb r4,[r1,r3]
    addlt r3,#1
    blt 1b
    cmp r4,#122               @> z
    strgtb r4,[r1,r3]
    addgt r3,#1
    bgt 1b
    add r4,r2
    cmp r4,#122
    subgt r4,#26
    strb r4,[r1,r3]
    add r3,#1
    b 1b

100:
    pop {r3,r4,lr}            @ restaur registers
    bx lr                     @ return
/******************************************************************/
/*     decrypt strings                                           */
/******************************************************************/
/* r0 contains the address of the encrypted string1 */
/* r1 contains the address of the decrypted string */
decryptRot13:
    push {r3,r4,lr}          @ save  registers
    mov r3,#0                @ counter byte string 1
    mov r2,#13                @ rot characters number
1:
    ldrb r4,[r0,r3]          @ load byte string 1
    cmp r4,#0                @ zero final ?
    streqb r4,[r1,r3]
    moveq r0,r3
    beq 100f
    cmp r4,#65               @ < A ?
    strltb r4,[r1,r3]
    addlt r3,#1
    blt 1b
    cmp r4,#90               @ > Z
    bgt 2f
    sub r4,r2                @ substract key
    cmp r4,#65               @ < A
    addlt r4,#26
    strb r4,[r1,r3]
    add r3,#1
    b 1b
2:
    cmp r4,#97               @ < a ?
    strltb r4,[r1,r3]
    addlt r3,#1
    blt 1b
    cmp r4,#122              @ > z
    strgtb r4,[r1,r3]
    addgt r3,#1
    bgt 1b
    sub r4,r2                @ substract key
    cmp r4,#97               @ < a
    addlt r4,#26
    strb r4,[r1,r3]
    add r3,#1
    b 1b

100:
    pop {r3,r4,lr}           @ restaur registers
    bx lr                    @ return
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
/* for this file see task include a file in language ARM assembly*/
.include "../affichage.inc"

implement a rot-13 function that replaces every letter of the ASCII alphabet with the letter which is "rotated" 13 characters around the 26 letter alphabet. The function should work on both upper and lower case letters, preserve case, and pass all non-alphabetic characters without alteration. Optionally, the function can be wrapped in a utility program that performs rot-13 encoding line-by-line for every line of input in each file listed on its command line or acts as a filter on its standard input.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program compositeSort.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 */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

/*******************************************/
/* Structures                               */
/********************************************/
/* city structure      */
    .struct  0
city_name:                             @
    .struct  city_name + 4
city_habitants:                             @
    .struct  city_habitants + 4
city_end:
/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessResult:        .asciz "Name : @  number habitants : @ \n"
szMessSortHab:      .asciz "Sort table for number of habitants :\n"
szMessSortName:     .asciz "Sort table for name of city :\n"
szCarriageReturn:   .asciz "\n"

// cities name
szCeret:           .asciz "Ceret"
szMaureillas:      .asciz "Maureillas"
szTaillet:         .asciz "Taillet"
szReynes:          .asciz "Reynes"
szVives:           .asciz "Vivés"
szBoulou:          .asciz "Le Boulou"
szSaintJean:       .asciz "Saint Jean Pla de Corts"
szCluses:          .asciz "Les Cluses"
szAlbere:          .asciz "L'Albère"
szPerthus:         .asciz "Le Perthus"
.align 4

TableCities:
                 .int szCluses         @ address name string
                 .int 251              @ number of habitants
                 .int szCeret
                 .int 7705
                 .int szMaureillas
                 .int 2596
                 .int szBoulou
                 .int 5554
                 .int szSaintJean
                 .int 2153
                 .int szAlbere
                 .int 83
                 .int szVives
                 .int 174
                 .int szTaillet
                 .int 115
                 .int szPerthus
                 .int 586
                 .int szReynes
                 .int 1354
.equ NBELEMENTS,  (. - TableCities) / city_end
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:        .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                             @ entry of program

    ldr r0,iAdrszMessSortHab
    bl affichageMess

    ldr r0,iAdrTableCities                        @ address city table
    mov r1,#0                                     @ not use in routine
    mov r2,#NBELEMENTS                            @ number of élements
    mov r3,#city_habitants                        @ sort by number habitants
    mov r4,#'N'                                   @ Alphanumeric
    bl shellSort
    ldr r0,iAdrTableCities                        @ address number table
    bl displayTable

    ldr r0,iAdrszMessSortName
    bl affichageMess

    ldr r0,iAdrTableCities                        @ address city table
    mov r1,#0                                     @ not use in routine
    mov r2,#NBELEMENTS                            @ number of élements
    mov r3,#city_name                             @ sort by name
    mov r4,#'A'                                   @ Alphanumeric
    bl shellSort
    ldr r0,iAdrTableCities                        @ address number table
    bl displayTable

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
iAdrsMessResult:          .int sMessResult
iAdrTableCities:          .int TableCities
iAdrszMessSortHab:        .int szMessSortHab
iAdrszMessSortName:       .int szMessSortName
/***************************************************/
/*   shell Sort                                    */
/***************************************************/

/* r0 contains the address of table */
/* r1 contains the first element but not use !!   */
/*   this routine use first element at index zero !!!  */
/* r2 contains the number of element */
/* r3 contains the offset of sort zone */
/* r4 contains type of sort zone N = numeric A = alphanumeric */
shellSort:
    push {r0-r12,lr}             @ save registers
    sub sp,#city_end             @ reserve area on stack
    mov fp,sp                    @ frame pointer = stack
    mov r8,r3                    @ save offser area sort
    mov r9,r4                    @ save type sort
    mov r7,#city_end             @ element size
    //vidregtit debut
    sub r12,r2,#1                @ index last item
    mov r6,r12                   @ init gap = last item
1:                               @ start loop 1
    lsrs r6,#1                   @ gap = gap / 2
    beq 100f                     @ if gap = 0 -> end
    mov r3,r6                    @ init loop indice 1
2:                               @ start loop 2
    mul r1,r3,r7                 @ offset élement
    mov r2,fp                    @ save on stack
    bl saveElement
    add r1,r8                    @ + offset sort zone
    ldr r4,[r0,r1]               @ load first value
    mov r5,r3                    @ init loop indice 2
3:                               @ start loop 3
    cmp r5,r6                    @ indice < gap
    blt 8f                       @ yes -> end loop 2
    sub r10,r5,r6                @ index = indice - gap
    mul r1,r10,r7                @ offset élement
    add r10,r1,r8                @ + offset sort zone
    ldr r2,[r0,r10]              @ load second value
    push {r3,r5}                 @ save registrars because not enought register
    cmp r9,#'A'                  @ sort area alapha ?
    beq 4f                       @ yes
    cmp r4,r2                    @  else compare numeric values
    bge 7f                       @ highter
    b 6f                         @ lower
4:                               @ compare area alphanumeric
    mov r10,#0                   @ counter
5:
    ldrb r3,[r4,r10]             @ byte string 1
    ldrb r5,[r2,r10]             @ byte string 2
    cmp r3,r5
    bgt 7f
    blt 6f

    cmp r3,#0                    @  end string 1
    beq 7f                       @ ens comparaison
    add r10,r10,#1               @ else add 1 in counter
    b 5b                         @ and loop

6:
    pop {r3,r5}                  @ restaur registers
    mul r2,r5,r7                 @ offset élement
    bl copyElement               @ copy element r1 to element r2
    sub r5,r6                    @ indice = indice - gap
    b 3b                         @ and loop
7:
    pop {r3,r5}
8:                               @ end loop 3
    mul r1,r5,r7                 @ offset destination élement
    mov r2,fp                    @ restaur element in table
    bl restaurElement
    add r3,#1                    @ increment indice 1
    cmp r3,r12                   @ end ?
    ble 2b                       @ no -> loop 2
    b 1b                         @ yes loop for new gap

100:                             @ end function
    add sp,#city_end
    pop {r0-r12,lr}              @ restaur registers
    bx lr                        @ return
/******************************************************************/
/*      copy table element                                */
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset origin element */
/* r2 offset destination element */
copyElement:
    push {r0-r4,lr}                                    @ save registers
    //vidregtit copy
    mov r3,#0
    add r1,r0
    add r2,r0
1:
    ldrb r4,[r1,r3]
    strb r4,[r2,r3]
    add r3,#1
    cmp r3,#city_end
    blt 1b
100:
    pop {r0-r4,lr}
    bx lr
/******************************************************************/
/*      save element                                */
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset origin element */
/* r2 address destination  */
saveElement:
    push {r0-r4,lr}                                    @ save registers
    mov r3,#0
    add r1,r0
1:
    ldrb r4,[r1,r3]
    strb r4,[r2,r3]
    add r3,#1
    cmp r3,#city_end
    blt 1b
100:
    pop {r0-r4,lr}
    bx lr
/******************************************************************/
/*      restaur element                                */
/******************************************************************/
/* r0 contains the address of table */
/* r1 offset destination element */
/* r2 address origine  */
restaurElement:
    push {r0-r4,lr}                                    @ save registers
    mov r3,#0
    add r1,r0
1:
    ldrb r4,[r2,r3]
    strb r4,[r1,r3]
    add r3,#1
    cmp r3,#city_end
    blt 1b
100:
    pop {r0-r4,lr}
    bx lr
/******************************************************************/
/*      Display table elements                                */
/******************************************************************/
/* r0 contains the address of table */
displayTable:
    push {r0-r6,lr}              @ save registers
    mov r2,r0                    @ table address
    mov r3,#0
    mov r6,#city_end
1:                               @ loop display table
    mul r4,r3,r6
    add r4,#city_name
    ldr r1,[r2,r4]
    ldr r0,iAdrsMessResult
    bl strInsertAtCharInc        @ put name in message
    mov r5,r0                    @ save address of new message
    mul r4,r3,r6
    add r4,#city_habitants       @ and load value
    ldr r0,[r2,r4]
    ldr r1,iAdrsZoneConv
    bl conversion10              @ call decimal conversion
    mov r0,r5
    ldr r1,iAdrsZoneConv         @ insert conversion in message
    bl strInsertAtCharInc
    bl affichageMess             @ display message
    add r3,#1
    cmp r3,#NBELEMENTS - 1
    ble 1b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
100:
    pop {r0-r6,lr}
    bx lr
iAdrsZoneConv:      .int sZoneConv

/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
Sort table for number of habitants :
Name : L'Albère  number habitants : 83
Name : Taillet  number habitants : 115
Name : Vivés  number habitants : 174
Name : Les Cluses  number habitants : 251
Name : Le Perthus  number habitants : 586
Name : Reynes  number habitants : 1354
Name : Saint Jean Pla de Corts  number habitants : 2153
Name : Maureillas  number habitants : 2596
Name : Le Boulou  number habitants : 5554
Name : Ceret  number habitants : 7705

Sort table for name of city :
Name : Ceret  number habitants : 7705
Name : L'Albère  number habitants : 83
Name : Le Boulou  number habitants : 5554
Name : Le Perthus  number habitants : 586
Name : Les Cluses  number habitants : 251
Name : Maureillas  number habitants : 2596
Name : Reynes  number habitants : 1354
Name : Saint Jean Pla de Corts  number habitants : 2153
Name : Taillet  number habitants : 115
Name : Vivés  number habitants : 174

sort an array of composite structures, specifically name-value pairs, by the key name using a custom comparator.


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

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
/* Initialized data */
.data
szMessX: .asciz "X"
szCarriageReturn:  .asciz "\n"

/* UnInitialized data */
.bss

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

    mov r2,#0       @ counter loop 1
1:       @ loop start 1
    mov r1,#0        @ counter loop 2
2:       @ loop start 2
    ldr r0,iAdrszMessX
    bl affichageMess
    add r1,#1       @ r1 + 1
    cmp r1,r2       @ compare r1 r2
    ble 2b        @ loop label 2 before
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    add r2,#1       @ r2 + 1
    cmp r2,#5       @ for five loop
    blt 1b         @ loop label 1 before

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

iAdrszMessX:  .int szMessX
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  */

demonstrate how to use nested for loops to print a specific pattern. The number of iterations in the inner loop is controlled by the outer loop, resulting in a pattern of increasing asterisks.


Works with: as version Raspberry Pi  or android 32 bits with application Termux
/* ARM assembly Raspberry PI  or android 32 bits */
/*  program hashmap.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 */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"
.equ MAXI, 10                   @ size hashmap
.equ HEAPSIZE,20000
.equ LIMIT, 10                  @ key characters number for compute index
.equ COEFF, 80                  @ filling rate 80 = 80%

/*******************************************/
/* Structures                               */
/********************************************/
/* structure hashMap   */
    .struct  0
hash_count:                       //  stored values counter
    .struct  hash_count + 4
hash_key:                         //  key
    .struct  hash_key + (4 * MAXI)
hash_data:                        // data
    .struct  hash_data + (4 * MAXI)
hash_fin:
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessFin:          .asciz "End program.\n"
szCarriageReturn:   .asciz "\n"
szMessNoP:          .asciz "Key not found !!!\n"
szKey1:             .asciz "one"
szData1:            .asciz "Ceret"
szKey2:             .asciz "two"
szData2:            .asciz "Maureillas"
szKey3:             .asciz "three"
szData3:            .asciz "Le Perthus"
szKey4:             .asciz "four"
szData4:            .asciz "Le Boulou"

.align 4
iptZoneHeap:    .int sZoneHeap            // start heap address
iptZoneHeapEnd: .int sZoneHeap + HEAPSIZE // end heap address
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
//sZoneConv:        .skip 24
tbHashMap1:       .skip hash_fin         @ hashmap
sZoneHeap:        .skip HEAPSIZE         @ heap
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                          @ entry of program

    ldr r0,iAdrtbHashMap1
    bl hashInit                @ init hashmap
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey1          @ store key one
    ldr r2,iAdrszData1
    bl hashInsert
    cmp r0,#0                  @ error ?
    bne 100f
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey2          @ store key two
    ldr r2,iAdrszData2
    bl hashInsert
    cmp r0,#0
    bne 100f
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey3          @ store key three
    ldr r2,iAdrszData3
    bl hashInsert
    cmp r0,#0
    bne 100f
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey4          @ store key four
    ldr r2,iAdrszData4
    bl hashInsert
    cmp r0,#0
    bne 100f

    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey2          @ remove key two
    bl hashRemoveKey
    cmp r0,#0
    bne 100f

    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey1         @ search key
    bl searchKey
    cmp r0,#-1
    beq 1f
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    b 2f
1:
    ldr r0,iAdrszMessNoP
    bl affichageMess
2:
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey2
    bl searchKey
    cmp r0,#-1
    beq 3f
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    b 4f
3:
    ldr r0,iAdrszMessNoP
    bl affichageMess
4:
    ldr r0,iAdrtbHashMap1
    ldr r1,iAdrszKey4
    bl searchKey
    cmp r0,#-1
    beq 5f
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    b 6f
5:
    ldr r0,iAdrszMessNoP
    bl affichageMess
6:
    ldr r0,iAdrszMessFin
    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
iAdrszMessFin:            .int szMessFin
iAdrtbHashMap1:           .int tbHashMap1
iAdrszKey1:               .int szKey1
iAdrszData1:              .int szData1
iAdrszKey2:               .int szKey2
iAdrszData2:              .int szData2
iAdrszKey3:               .int szKey3
iAdrszData3:              .int szData3
iAdrszKey4:               .int szKey4
iAdrszData4:              .int szData4
iAdrszMessNoP:            .int szMessNoP
/***************************************************/
/*     init hashMap               */
/***************************************************/
// r0 contains address to hashMap
hashInit:
    push {r1-r3,lr}             @ save  registers
    mov r1,#0
    mov r2,#0
    str r2,[r0,#hash_count]      @ init counter
    add r0,r0,#hash_key         @ start zone key/value
1:
    lsl r3,r1,#3
    add r3,r3,r0
    str r2,[r3,#hash_key]
    str r2,[r3,#hash_data]
    add r1,r1,#1
    cmp r1,#MAXI
    blt 1b
100:
    pop {r1-r3,pc}             @ restaur registers
/***************************************************/
/*     insert key/datas               */
/***************************************************/
// r0 contains address to hashMap
// r1 contains address to key
// r2 contains address to datas
hashInsert:
    push {r1-r8,lr}             @ save  registers
    mov r6,r0                   @ save address
    bl hashIndex                @ search void key or identical key
    cmp r0,#0                   @ error ?
    blt 100f

    ldr r3,iAdriptZoneHeap
    ldr r3,[r3]
    ldr r8,iAdriptZoneHeapEnd
    ldr r8,[r8]
    sub r8,r8,#50
    lsl r0,r0,#2               @ 4 bytes
    add r7,r6,#hash_key        @ start zone key/value
    ldr r4,[r7,r0]
    cmp r4,#0                  @ key already stored ?
    bne 1f
    ldr r4,[r6,#hash_count]    @ no -> increment counter
    add r4,r4,#1
    cmp r4,#(MAXI * COEFF / 100)
    bge 98f
    str r4,[r6,#hash_count]
1:
    str r3,[r7,r0]
    mov r4,#0
2:                            @ copy key loop in heap
    ldrb r5,[r1,r4]
    strb r5,[r3,r4]
    cmp r5,#0
    add r4,r4,#1
    bne 2b
    add r3,r3,r4
    cmp r3,r8
    bge 99f
    add r7,r6,#hash_data
    str r3,[r7,r0]
    mov r4,#0
3:                            @ copy data loop in heap
    ldrb r5,[r2,r4]
    strb r5,[r3,r4]
    cmp r5,#0
    add r4,r4,#1
    bne 3b
    add r3,r3,r4
    cmp r3,r8
    bge 99f
    ldr r0,iAdriptZoneHeap
    str r3,[r0]               @ new heap address

    mov r0,#0                 @ insertion OK
    b 100f
98:                           @ error hashmap
    adr r0,szMessErrInd
    bl affichageMess
    mov r0,#-1
    b 100f
99:                           @ error heap
    adr r0,szMessErrHeap
    bl affichageMess
    mov r0,#-1
100:
    pop {r1-r8,lr}             @ restaur registers
    bx lr                      @ return
szMessErrInd:          .asciz "Error : HashMap size Filling rate Maxi !!\n"
szMessErrHeap:         .asciz "Error : Heap size  Maxi !!\n"
.align 4
iAdriptZoneHeap:       .int iptZoneHeap
iAdriptZoneHeapEnd:    .int iptZoneHeapEnd
/***************************************************/
/*     search void index in hashmap              */
/***************************************************/
// r0 contains hashMap address
// r1 contains key address
hashIndex:
    push {r1-r4,lr}       @ save  registers
    add r4,r0,#hash_key
    mov r2,#0             @ index
    mov r3,#0             @ characters sum
1:                        @ loop to compute characters sum
    ldrb r0,[r1,r2]
    cmp r0,#0             @ string end ?
    beq 2f
    add r3,r3,r0          @ add to sum
    add r2,r2,#1
    cmp r2,#LIMIT
    blt 1b
2:
    mov r5,r1             @ save key address
    mov r0,r3
    mov r1,#MAXI
    bl division           @ compute remainder -> r3
    mov r1,r5             @ key address

3:
    ldr r0,[r4,r3,lsl #2] @ loak key for computed index
    cmp r0,#0             @ void key ?
    beq 4f
    bl comparStrings      @ identical key ?
    cmp r0,#0
    beq 4f                @ yes
    add r3,r3,#1          @ no search next void key
    cmp r3,#MAXI          @ maxi ?
    movge r3,#0           @ restart to index 0
    b 3b
4:
    mov r0,r3             @ return index void array or key equal
100:
    pop {r1-r4,pc}        @ restaur registers

/***************************************************/
/*     search key in hashmap              */
/***************************************************/
// r0 contains hash map address
// r1 contains key address
searchKey:
    push {r1-r2,lr}           @ save  registers
    mov r2,r0
    bl hashIndex
    lsl r0,r0,#2
    add r1,r0,#hash_key
    ldr r1,[r2,r1]
    cmp r1,#0
    moveq r0,#-1
    beq 100f
    add r1,r0,#hash_data
    ldr r0,[r2,r1]
100:
    pop {r1-r2,pc}            @ restaur registers
/***************************************************/
/*     remove key in hashmap              */
/***************************************************/
// r0 contains hash map address
// r1 contains key address
hashRemoveKey:                  @ INFO: hashRemoveKey
    push {r1-r3,lr}             @ save  registers
    mov r2,r0
    bl hashIndex
    lsl r0,r0,#2
    add r1,r0,#hash_key
    ldr r3,[r2,r1]
    cmp r3,#0
    beq  2f
    add r3,r2,r1
    mov r1,#0                   @ raz key address
    str r1,[r3]
    add r1,r0,#hash_data
    add r3,r2,r1
    mov r1,#0
    str r1,[r3]                 @ raz datas address
    mov r0,#0
    b 100f
2:
    adr r0,szMessErrRemove
    bl affichageMess
    mov r0,#-1
100:
    pop {r1-r3,pc}            @ restaur registers
szMessErrRemove:         .asciz "\033[31mError remove key !!\033[0m\n"
.align 4
/************************************/
/* Strings case sensitive comparisons  */
/************************************/
/* r0 et r1 contains the address of strings */
/* return 0 in r0 if equals */
/* return -1 if string r0 < string r1 */
/* return 1  if string r0 > string r1 */
comparStrings:
    push {r1-r4}         @ save des registres
    mov r2,#0            @ characters counter
1:
    ldrb r3,[r0,r2]      @ byte string 1
    ldrb r4,[r1,r2]      @ byte string 2
    cmp r3,r4
    movlt r0,#-1         @ smaller
    movgt r0,#1	         @ greather
    bne 100f             @ not equals
    cmp r3,#0            @ 0 end string ?
    moveq r0,#0          @ equals
    beq 100f             @ end string
    add r2,r2,#1         @ else add 1 in counter
    b 1b                 @ and loop
100:
    pop {r1-r4}
    bx lr
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"

"Create an associative array, also known as a dictionary, map, or hash."


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

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

.equ NBELEMENTS,      100                @ list size

/*******************************************/
/* Structures                               */
/********************************************/
/* structure linkedlist*/
    .struct  0
llist_next:                               @ next element
    .struct  llist_next + 4
llist_value:                              @ element value
    .struct  llist_value + 4
llist_fin:
/* Initialized data */
.data
szMessInitListe:         .asciz "List initialized.\n"
szCarriageReturn:        .asciz "\n"
/* datas error display */
szMessErreur:            .asciz "Error detected.\n"
/* datas message display */
szMessResult:            .ascii "Element No :"
sNumElement:             .space 12,' '
                         .ascii " value :  "
sValue:                  .space 12,' '
                         .asciz "\n"

/* UnInitialized data */
.bss
lList1:              .skip llist_fin * NBELEMENTS    @ list memory place
/*  code section */
.text
.global main
main:
    ldr r0,iAdrlList1
    mov r1,#0                           @ list init
    str r1,[r0,#llist_next]
    ldr r0,iAdrszMessInitListe
    bl affichageMess
    ldr r0,iAdrlList1
    mov r1,#2
    bl insertElement                    @ add element value 2
    ldr r0,iAdrlList1
    mov r1,#5
    bl insertElement                    @ add element value 5
    ldr r3,iAdrlList1
    mov r2,#0                           @ ident element
1:
    ldr r0,[r3,#llist_next]             @ end list ?
    cmp r0,#0
    beq 100f                            @ yes
    add r2,#1
    mov r0,r2                           @ display No element and value
    ldr r1,iAdrsNumElement
    bl conversion10S
    ldr r0,[r3,#llist_value]
    ldr r1,iAdrsValue
    bl conversion10S
    ldr r0,iAdrszMessResult
    bl affichageMess
    ldr r3,[r3,#llist_next]             @ next element
    b 1b                                @ and loop
100:                                    @ standard end of the program
    mov r7, #EXIT                       @ request to exit program
    svc 0                               @ perform system call
iAdrszMessInitListe:       .int szMessInitListe
iAdrszMessErreur:          .int szMessErreur
iAdrszCarriageReturn:      .int szCarriageReturn
iAdrlList1:                .int lList1
iAdrszMessResult:          .int szMessResult
iAdrsNumElement:           .int sNumElement
iAdrsValue:                .int sValue

/******************************************************************/
/*     insert element at end of list                          */
/******************************************************************/
/* r0 contains the address of the list */
/* r1 contains the value of element  */
/* r0 returns address of element or - 1 if error */
insertElement:
    push {r1-r3,lr}                       @ save  registers
    mov r2,#llist_fin * NBELEMENTS
    add r2,r0                             @ compute address end list
1:                                        @ start loop
    ldr r3,[r0,#llist_next]               @ load next pointer
    cmp r3,#0                             @ = zero
    movne r0,r3                           @ no -> loop with pointer
    bne 1b
    add r3,r0,#llist_fin                  @ yes -> compute next free address
    cmp r3,r2                             @ > list end
    movge r0,#-1                          @ yes -> error
    bge 100f
    str r3,[r0,#llist_next]               @ store next address in current pointer
    str r1,[r0,#llist_value]              @ store element value
    mov r1,#0
    str r1,[r3,#llist_next]               @ init next pointer in next address

100:
    pop {r1-r3,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  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
/***************************************************/
/*  Converting a register to a signed decimal      */
/***************************************************/
/* r0 contains value and r1 area address    */
conversion10S:
    push {r0-r4,lr}       @ save registers
    mov r2,r1             @ debut zone stockage
    mov r3,#'+'           @ par defaut le signe est +
    cmp r0,#0             @ negative number ?
    movlt r3,#'-'         @ yes
    mvnlt r0,r0           @ number inversion
    addlt r0,#1
    mov r4,#10            @ length area
1:                        @ start loop
    bl divisionpar10U
    add r1,#48            @ digit
    strb r1,[r2,r4]       @ store digit on area
    sub r4,r4,#1          @ previous position
    cmp r0,#0             @ stop if quotient = 0
    bne 1b

    strb r3,[r2,r4]       @ store signe
    subs r4,r4,#1         @ previous position
    blt  100f             @ if r4 < 0 -> end

    mov r1,#' '           @ space
2:
    strb r1,[r2,r4]       @store byte space
    subs r4,r4,#1         @ previous position
    bge 2b                @ loop if r4 > 0
100:
    pop {r0-r4,lr}        @ restaur registers
    bx lr
/***************************************************/
/*   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

"Defines a method to insert an element into a singly-linked list after a specified element. Specifically, it inserts element C into a list of elements A->B, after element A."


Works with: as version Raspberry Pi  or android 32 bits with application Termux
/* ARM assembly Raspberry PI  */
/*  program multieth.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 */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes                       */
/************************************/
.include "../constantes.inc"

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessResult:         .asciz "Result : "
szMessStart:          .asciz "Program 32 bits start.\n"
szCarriageReturn:     .asciz "\n"
szMessErreur:         .asciz "Error overflow. \n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:             .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                            @ entry of program
    ldr r0,iAdrszMessStart
    bl affichageMess
    mov r0,#17
    mov r1,#34
    bl multEthiop
    ldr r1,iAdrsZoneConv
    bl conversion10              @ decimal conversion
    mov r0,#3                    @ number string to display
    ldr r1,iAdrszMessResult
    ldr r2,iAdrsZoneConv         @ insert conversion in message
    ldr r3,iAdrszCarriageReturn
    bl displayStrings            @ display message

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
iAdrsZoneConv:               .int sZoneConv
iAdrszMessResult:            .int szMessResult
iAdrszMessErreur:            .int szMessErreur
iAdrszMessStart:             .int szMessStart
/******************************************************************/
/*     Ethiopian multiplication                                  */
/******************************************************************/
/*  r0  first factor */
/*  r1   2th  factor  */
/*  r0 return résult  */
multEthiop:
    push {r1-r3,lr}            @ save registers
    mov r2,#0                  @ init result
 1:                            @ loop
    cmp r0,#1                  @ end ?
    blt 3f
    ands r3,r0,#1              @
    addne r2,r1                @ add factor2 to result
    lsr r0,#1                  @ divide factor1 by 2
    lsls r1,#1                 @ multiply factor2 by 2
    bcs 2f                     @ overflow ?
    b 1b                       @ or loop
 2:                            @ error display
    ldr r0,iAdrszMessErreur
    bl affichageMess
    mov r2,#0
 3:
    mov r0,r2                  @ return result
    pop {r1-r3,pc}
/***************************************************/
/*   display multi strings                    */
/***************************************************/
/* r0  contains number strings address */
/* r1 address string1 */
/* r2 address string2 */
/* r3 address string3 */
/* other address on the stack */
/* thinck to add  number other address * 4 to add to the stack */
displayStrings:            @ INFO:  displayStrings
    push {r1-r4,fp,lr}     @ save des registres
    add fp,sp,#24          @ save paraméters address (6 registers saved * 4 bytes)
    mov r4,r0              @ save strings number
    cmp r4,#0              @ 0 string -> end
    ble 100f
    mov r0,r1              @ string 1
    bl affichageMess
    cmp r4,#1              @ number > 1
    ble 100f
    mov r0,r2
    bl affichageMess
    cmp r4,#2
    ble 100f
    mov r0,r3
    bl affichageMess
    cmp r4,#3
    ble 100f
    mov r3,#3
    sub r2,r4,#4
1:                         @ loop extract address string on stack
    ldr r0,[fp,r2,lsl #2]
    bl affichageMess
    subs r2,#1
    bge 1b
100:
    pop {r1-r4,fp,pc}

/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"

The code defines three functions for halving an integer, doubling an integer, and checking if an integer is even. These functions are used to implement Ethiopian multiplication, a method of multiplying integers using addition, doubling, and halving. The multiplication process involves creating a table, discarding rows with even numbers in the left column, and summing the remaining values in the right column.