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.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program game24Solver.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 STDIN,      0       @ Linux input console
.equ READ,       3       @ Linux syscall
.equ NBDIGITS,   4       @ digits number
.equ TOTAL,      24
.equ BUFFERSIZE, 80

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessRules:        .ascii "24 Game\n"
                    .ascii "The program will display four randomly-generated \n"
                    .asciz "single-digit numbers and search a solution for a total to 24\n\n"

szMessDigits:       .asciz "The four digits are @ @ @ @ and the score is 24. \n"
szMessOK:           .asciz "Solution : \n"
szMessNotOK:        .asciz "No solution for this problem !! \n"
szMessNewGame:      .asciz "New game (y/n) ? \n"
szCarriageReturn:   .asciz "\n"
.align 4
iGraine:            .int 123456
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
sZoneConv:        .skip 24
sBuffer:          .skip BUFFERSIZE
iTabDigit:        .skip 4 * NBDIGITS @ digits table
iTabOperand1:     .skip 4 * NBDIGITS @ operand 1 table
iTabOperand2:     .skip 4 * NBDIGITS @ operand 2 table
iTabOperation:    .skip 4 * NBDIGITS @ operator table
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                 @ entry of program

    ldr r0,iAdrszMessRules            @ display rules
    bl affichageMess
1:
    mov r3,#0
    ldr r12,iAdriTabDigit
    ldr r5,iAdrszMessDigits
2:                                    @ loop generate random digits
    mov r0,#8
    bl genereraleas
    add r0,r0,#1
    str r0,[r12,r3,lsl #2]            @ store in table
    ldr r1,iAdrsZoneConv
    bl conversion10                   @ call decimal conversion
    mov r2,#0
    strb r2,[r1,r0]                   @ reduce size display area with zéro final
    mov r0,r5
    ldr r1,iAdrsZoneConv              @ insert conversion in message
    bl strInsertAtCharInc
    mov r5,r0
    add r3,r3,#1
    cmp r3,#NBDIGITS                  @ end ?
    blt 2b                            @ no -> loop
    mov r0,r5
    bl affichageMess

    mov r0,#0                         @ start leval
    mov r1,r12                        @ address digits table
    bl searchSoluce
    cmp r0,#-1                        @ solution ?
    bne 3f                            @ no
    ldr r0,iAdrszMessOK
    bl affichageMess
    bl writeSoluce                    @ yes -> write solution in buffer
    ldr r0,iAdrsBuffer                @ and display buffer
    bl affichageMess
    b 10f
3:                                    @ display message no solution
    ldr r0,iAdrszMessNotOK
    bl affichageMess

10:                                   @ display new game ?
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    ldr r0,iAdrszMessNewGame
    bl affichageMess
    bl saisie
    cmp r0,#'y'
    beq 1b
    cmp r0,#'Y'
    beq 1b

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
iAdrszMessRules:          .int szMessRules
iAdrszMessDigits:         .int szMessDigits
iAdrszMessNotOK:          .int szMessNotOK
iAdrszMessOK:             .int szMessOK
iAdrszMessNewGame:        .int szMessNewGame
iAdrsZoneConv:            .int sZoneConv
iAdriTabDigit:            .int iTabDigit
/******************************************************************/
/*            recherche solution                                       */
/******************************************************************/
/* r0 level   */
/* r1 table value address */
/* r0 return -1 if ok     */
searchSoluce:
    push {r1-r12,lr}                @ save registers
    sub sp,#4* NBDIGITS             @ reserve size new digits table
    mov fp,sp                       @ frame pointer = address stack
    mov r10,r1                      @ save table
    add r9,r0,#1                    @ new  level
    rsb r3,r9,#NBDIGITS             @ last element digits table
    ldr r4,[r1,r3,lsl #2]           @ load last element
    cmp r4,#TOTAL                   @ equal to total to search ?
    bne 0f                          @ no
    cmp r9,#NBDIGITS                @ all digits are used ?
    bne 0f                          @ no
    mov r0,#-1                      @ yes -> it is ok -> end
    b 100f
0:
    mov r5,#0                       @ indice loop 1
1:                                  @ begin loop 1
    cmp r5,r3
    bge 9f
    ldr r4,[r10,r5,lsl #2]          @ load first operand
    ldr r8,iAdriTabOperand1
    str r4,[r8,r9,lsl #2]           @ and store in operand1 table
    add r6,r5,#1                    @ indice loop 2
2:                                  @ begin loop 2
    cmp r6,r3
    bgt 8f
    ldr r12,[r10,r6,lsl #2]         @ load second operand
    ldr r8,iAdriTabOperand2
    str r12,[r8,r9,lsl #2]          @ and store in operand2 table
    mov r7,#0   @ k
    mov r8,#0   @ n
3:
    cmp r7,r5
    beq 4f
    cmp r7,r6
    beq 4f
    ldr r0,[r10,r7,lsl #2]          @ copy other digits in new table on stack
    str r0,[fp,r8,lsl #2]
    add r8,r8,#1
4:
    add r7,r7,#1
    cmp r7,r3
    ble 3b

    add r7,r4,r12                   @ addition test
    str r7,[fp,r8,lsl #2]           @ store result of addition
    mov r7,#'+'
    ldr r0,iAdriTabOperation
    str r7,[r0,r9,lsl #2]           @ store operator
    mov r0,r9                       @ pass new level
    mov r1,fp                       @ pass new table address on stack
    bl searchSoluce
    cmp r0,#0
    blt 100f
                                    @ soustraction test
    cmp r4,r12
    subgt r7,r4,r12
    suble r7,r12,r4
    str r7,[fp,r8,lsl #2]
    mov r7,#'-'
    ldr r0,iAdriTabOperation
    str r7,[r0,r9,lsl #2]
    mov r0,r9
    mov r1,fp
    bl searchSoluce
    cmp r0,#0
    blt 100f

    mul r7,r4,r12                    @ multiplication test
    str r7,[fp,r8,lsl #2]
    mov r7,#'*'
    //vidregtit mult
    ldr r0,iAdriTabOperation
    str r7,[r0,r9,lsl #2]
    mov r0,r9
    mov r1,fp
    bl searchSoluce
    cmp r0,#0
    blt 100f
5:                                    @ division test
    push {r1-r3}
    mov r0,r4
    mov r1,r12
    bl division
   // mov r7,r9
    cmp r3,#0
    bne 6f
    str r2,[fp,r8,lsl #2]
    mov r7,#'/'
    ldr r0,iAdriTabOperation
    str r7,[r0,r9,lsl #2]
    mov r0,r9
    mov r1,fp
    bl searchSoluce
    b 7f
6:
    mov r0,r12
    mov r1,r4
    bl division
    cmp r3,#0
    bne 7f
    str r2,[fp,r8,lsl #2]
    mov r7,#'/'
    ldr r0,iAdriTabOperation
    str r7,[r0,r9,lsl #2]
    mov r0,r9
    mov r1,fp
    bl searchSoluce
7:
    pop {r1-r3}
    cmp r0,#0
    blt 100f

    add r6,r6,#1                      @ increment indice loop 2
    b 2b

8:
    add r5,r5,#1                      @ increment indice loop 1
    b 1b
9:

100:
    add sp,#4* NBDIGITS               @ stack alignement
    pop {r1-r12,lr}
    bx lr                             @ return
iAdriTabOperand1:         .int iTabOperand1
iAdriTabOperand2:         .int iTabOperand2
iAdriTabOperation:        .int iTabOperation
/******************************************************************/
/*            write solution                                      */
/******************************************************************/
writeSoluce:
    push {r1-r12,lr}            @ save registers
    ldr r6,iAdriTabOperand1
    ldr r7,iAdriTabOperand2
    ldr r8,iAdriTabOperation
    ldr r10,iAdrsBuffer
    mov r4,#0                    @ buffer indice
    mov r9,#1
1:
    ldr r5,[r6,r9,lsl #2]       @ operand 1
    ldr r11,[r7,r9,lsl #2]       @ operand  2
    ldr r12,[r8,r9,lsl #2]       @ operator
    cmp r12,#'-'
    beq 2f
    cmp r12,#'/'
    beq 2f
    b 3f
2:                               @ if division or soustraction
    cmp r5,r11                   @ reverse operand if operand 1 is < operand 2
    movlt r2,r5
    movlt r5,r11
    movlt r11,r2
3:                               @ conversion operand 1 = r0
    mov r0,r5
    mov r1,#10
    bl division
    cmp r2,#0
    addne r2,r2,#0x30
    strneb r2,[r10,r4]
    addne r4,r4,#1
    add r3,r3,#0x30
    strb r3,[r10,r4]
    add r4,r4,#1
    ldr r2,[r7,r9,lsl #2]

    strb r12,[r10,r4]           @ operator
    add r4,r4,#1

    mov r0,r11                  @ conversion operand  2
    mov r1,#10
    bl division
    cmp r2,#0
    addne r2,r2,#0x30
    strneb r2,[r10,r4]
    addne r4,r4,#1
    add r3,r3,#0x30
    strb r3,[r10,r4]
    add r4,r4,#1

    mov r0,#'='
    str r0,[r10,r4]             @ conversion sous total
    add r4,r4,#1
    cmp r12,#'+'
    addeq r0,r5,r11
    cmp r12,#'-'
    subeq r0,r5,r11
    cmp r12,#'*'
    muleq r0,r5,r11
    cmp r12,#'/'
    udiveq r0,r5,r11

    mov r1,#10
    bl division
    cmp r2,#0
    addne r2,r2,#0x30
    strneb r2,[r10,r4]
    addne r4,r4,#1
    add r3,r3,#0x30
    strb r3,[r10,r4]
    add r4,r4,#1
    mov r0,#'\n'
    str r0,[r10,r4]
    add r4,r4,#1

    add r9,#1
    cmp r9,#NBDIGITS
    blt 1b
    mov r1,#0
    strb r1,[r10,r4]            @ store 0 final

100:
    pop {r1-r12,lr}
    bx lr                       @ return
iAdrsBuffer:         .int sBuffer

/******************************************************************/
/*            string entry                                       */
/******************************************************************/
/* r0 return the first character of human entry */
saisie:
    push {r1-r7,lr}        @ save registers
    mov r0,#STDIN          @ Linux input console
    ldr r1,iAdrsBuffer     @ buffer address
    mov r2,#BUFFERSIZE     @ buffer size
    mov r7,#READ           @ request to read datas
    svc 0                  @ call system
    ldr r1,iAdrsBuffer     @ buffer address
    ldrb r0,[r1]           @ load first character
100:
    pop {r1-r7,lr}
    bx lr                   @ return
/***************************************************/
/*   Generation random number                  */
/***************************************************/
/* r0 contains limit  */
genereraleas:
    push {r1-r4,lr}         @ save registers
    ldr r4,iAdriGraine
    ldr r2,[r4]
    ldr r3,iNbDep1
    mul r2,r3,r2
    ldr r3,iNbDep2
    add r2,r2,r3
    str r2,[r4]             @ maj de la graine pour l appel suivant
    cmp r0,#0
    beq 100f
    add r1,r0,#1            @ divisor
    mov r0,r2               @ dividende
    bl division
    mov r0,r3               @ résult = remainder

100:                        @ end function
    pop {r1-r4,lr}          @ restaur registers
    bx lr                   @ return
/*****************************************************/
iAdriGraine: .int iGraine
iNbDep1:     .int 0x343FD
iNbDep2:     .int 0x269EC3
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"

The code accepts four digits, either from user input or randomly generated, and calculates arithmetic expressions following the 24 game rules. It also displays examples of the solutions it generates.


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

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

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessLargeNumber:   .asciz "Number N to large. \n"
szMessNegNumber:      .asciz "Number N is negative. \n"

szMessResult:  .ascii "Resultat = "      @ message result
sMessValeur:   .fill 12, 1, ' '
                   .asciz "\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                @ entry of program
    push {fp,lr}      @ saves 2 registers

    mov r0,#-5
    bl factorial
    mov r0,#10
    bl factorial
    mov r0,#20
    bl factorial

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

/********************************************/
/*     calculation                         */
/********************************************/
/* r0 contains number N */
factorial:
    push {r1,r2,lr}    	@ save  registres
    cmp r0,#0
    blt 99f
    beq 100f
    cmp r0,#1
    beq 100f
    bl calFactorial
    cmp r0,#-1          @ overflow ?
    beq 98f
    ldr r1,iAdrsMessValeur
    bl conversion10       @ call function with 2 parameter (r0,r1)
    ldr r0,iAdrszMessResult
    bl affichageMess            @ display message
    b 100f

98:   @ display error message
    ldr r0,iAdrszMessLargeNumber
    bl affichageMess
    b 100f
99:  @ display error message
    ldr r0,iAdrszMessNegNumber
    bl affichageMess

100:
    pop {r1,r2,lr}    			@ restaur registers
    bx lr	        			@ return
iAdrszMessNegNumber:       .int szMessNegNumber
iAdrszMessLargeNumber:	    .int szMessLargeNumber
iAdrsMessValeur:            .int sMessValeur
iAdrszMessResult:          .int szMessResult
/******************************************************************/
/*     calculation                         */
/******************************************************************/
/* r0 contains the number N */
calFactorial:
    cmp r0,#1          @ N = 1 ?
    bxeq lr           @ yes -> return
    push {fp,lr}    		@ save  registers
    sub sp,#4           @ 4 byte on the stack
    mov fp,sp           @ fp <- start address stack
    str r0,[fp]                    @ fp contains  N
    sub r0,#1          @ call function with N - 1
    bl calFactorial
    cmp r0,#-1         @ error overflow ?
    beq 100f         @ yes -> return
    ldr r1,[fp]       @ load N
    umull r0,r2,r1,r0   @ multiply result by N
    cmp r2,#0           @ r2 is the hi rd  if <> 0 overflow
    movne r0,#-1      @ if overflow  -1 -> r0

100:
    add sp,#4            @ free 4 bytes on stack
    pop {fp,lr}    			@ restau2 registers
    bx lr	        		@ return

/******************************************************************/
/*     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  */
/******************************************************************/
/*     Converting a register to a decimal                                 */
/******************************************************************/
/* r0 contains value and r1 address area   */
conversion10:
    push {r1-r4,lr}    /* save registers */
    mov r3,r1
    mov r2,#10

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

100:
    pop {r1-r4,lr}    @ restaur registres
    bx lr	          @return
/***************************************************/
/*   division par 10   signé                       */
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/*
/* and   http://www.hackersdelight.org/            */
/***************************************************/
/* r0 dividende   */
/* r0 quotient */
/* r1 remainder  */
divisionpar10:
  /* r0 contains the argument to be divided by 10 */
   push {r2-r4}   /* save registers  */
   mov r4,r0
   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

The code defines a function that calculates the factorial of a given number. The factorial is the product of all positive integers from the given number down to 1. The function can be implemented either iteratively or recursively. It optionally includes error handling for negative input numbers. It is related to the task of generating primorial numbers.


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

/* REMARK 1 : this program use routines in a include file
   see task Include a file language arm assembly
   for the routine affichageMess conversion10
   see at end of this program the instruction include */

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

.equ BUFSIZE,  10000
.equ LINESIZE, 100

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessErreur:     .asciz "Erreur ouverture fichier input.\n"
szMessErreur1:    .asciz "Erreur fermeture fichier.\n"
szMessErreur2:    .asciz "Erreur lecture fichier.\n"
szCarriageReturn: .asciz "\n"
szMessEndLine:    .asciz "<<<<<< End line.\n"

szNameFileInput:    .asciz "input.txt"

/*******************************************/
/* DONNEES NON INITIALISEES                */
/*******************************************/
.bss
sBuffer:      .skip BUFSIZE
sBufferWord:  .skip LINESIZE
/**********************************************/
/* -- Code section                            */
/**********************************************/
.text
.global main
main:
    /* open file */
    ldr r0,iAdrszNameFileInput      @ file name
    mov r1,#O_RDONLY                @  flags
    mov r2,#0                       @ mode
    mov r7,#OPEN                    @ call system OPEN
    svc #0
    cmp r0,#0                       @ open error ?
    ble erreur
    /* read file  */
    mov r9,r0                       @ save File Descriptor
    ldr r1,iAdrsBuffer              @ buffer address
    mov r2,#BUFSIZE                 @ buffer size
    mov r7, #READ                   @ call system  READ
    svc 0
    cmp r0,#0                       @ read error ?
    ble erreur2
    mov r2,r0                       @ length read characters
    /* buffer analyze   */
    ldr r3,iAdrsBuffer              @ buffer address
    ldr r5,iAdrsBufferWord          @ buffer address
    mov r7,#0                       @ word byte counter
    mov r4,#0                       @ byte counter
1:
    ldrb r6,[r3,r4]                 @ load byte buffer
    cmp r6,#' '                     @ space ?
    moveq r8,#0                     @ yes
    beq 2f
    cmp r6,#0xA                     @ end line ?
    moveq r8,#1
    beq 2f
    cmp r6,#0xD                     @ end line ?
    beq 3f
    strb r6,[r5,r7]                 @ store byte
    add r7,#1                       @ increment word byte counter
    b 4f
2:                                  @ word end
    cmp r7,#0
    beq 3f
    mov r6,#0                       @ store 0 final
    strb r6,[r5,r7]
    mov r0,r5                       @ display word
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    mov r7,#0                       @ raz word byte counter
3:
    cmp r8,#1                       @ end line ?
    bne 4f
    ldr r0,iAdrszMessEndLine
    bl affichageMess
4:
    add r4,#1                       @ increment read buffer counter
    cmp r4,r2                       @ end bytes ?
    blt 1b                          @ no -> loop

4:
    /* close imput file */
    mov r0,r9                       @ Fd
    mov r7, #CLOSE                  @ call system CLOSE
    svc 0
    cmp r0,#0                       @ close error ?
    blt erreur1

    mov r0,#0     @ return code OK
    b 100f
erreur:
    ldr r1,iAdrszMessErreur
    bl displayError
    mov r0,#1       @ error return code
    b 100f
erreur1:
    ldr r1,iAdrszMessErreur1
    bl displayError
    mov r0,#1       @ error return code
    b 100f
erreur2:
    ldr r1,iAdrszMessErreur2
    bl displayError
    mov r0,#1       @ error return code
    b 100f

100:        @ end program
    mov r7, #EXIT
    svc 0
iAdrszNameFileInput:      .int szNameFileInput
iAdrszMessErreur:         .int szMessErreur
iAdrszMessErreur1:        .int szMessErreur1
iAdrszMessErreur2:        .int szMessErreur2
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrszMessEndLine:        .int szMessEndLine
iAdrsBuffer:              .int sBuffer
iAdrsBufferWord:          .int sBufferWord
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"

"Continuously read words or lines from a text stream until there is no more data available."


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program createXml.s   */
/* install package   libxml++2.6-dev    */
/* link with gcc option -lxml2    */

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

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessEndpgm:      .asciz "Normal end of program.\n"
szFileName:        .asciz "file1.xml"
szFileMode:        .asciz "w"
szMessError:       .asciz "Error detected !!!!. \n"

szVersDoc:         .asciz "1.0"
szLibRoot:         .asciz "root"
szLibElement:      .asciz "element"
szText:            .asciz "some text here"
szCarriageReturn:  .asciz "\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4

/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                     @ entry of program
    ldr r0,iAdrszVersDoc
    bl xmlNewDoc                          @ create doc
    mov r9,r0                             @ doc address
    mov r0,#0
    ldr r1,iAdrszLibRoot
    bl xmlNewNode                         @ create root node
    mov r8,r0                             @ node root address
    mov r0,r9
    mov r1,r8
    bl xmlDocSetRootElement
@TODO voir la gestion des erreurs

    mov r0,#0
    ldr r1,iAdrszLibElement
    bl xmlNewNode                         @ create element node
    mov r7,r0                             @ node element address
    ldr r0,iAdrszText
    bl xmlNewText                         @ create text
    mov r6,r0                             @ text address
    mov r0,r7                             @ node element address
    mov r1,r6                             @ text address
    bl xmlAddChild                        @ add text to element node
    mov r0,r8                             @ node root address
    mov r1,r7                             @ node element address
    bl xmlAddChild                        @ add node elemeny to root node
    ldr r0,iAdrszFileName
    ldr r1,iAdrszFileMode
    bl fopen                              @ file open
    cmp r0,#0
    blt 99f
    mov r5,r0                             @ File descriptor
    mov r1,r9                             @ doc
    mov r2,r8                             @ root
    bl xmlElemDump                        @ write xml file
    cmp r0,#0
    blt 99f
    mov r0,r5
    bl fclose                             @ file close
    mov r0,r9
    bl xmlFreeDoc
    bl xmlCleanupParser
    ldr r0,iAdrszMessEndpgm
    bl affichageMess
    b 100f
99:
    @ error
    ldr r0,iAdrszMessError
    bl affichageMess
100:                                       @ standard end of the program
    mov r0, #0                             @ return code
    mov r7, #EXIT                          @ request to exit program
    svc #0                                 @ perform the system call

iAdrszMessError:          .int szMessError
iAdrszMessEndpgm:         .int szMessEndpgm
iAdrszVersDoc:            .int szVersDoc
iAdrszLibRoot:            .int szLibRoot
iAdrszLibElement:         .int szLibElement
iAdrszText:               .int szText
iAdrszFileName:           .int szFileName
iAdrszFileMode:           .int szFileMode
iAdrszCarriageReturn:     .int szCarriageReturn

/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                   @ save  registres
    mov r2,#0                               @ counter length
1:                                          @ loop length calculation
    ldrb r1,[r0,r2]                         @ read octet start position + index
    cmp r1,#0                               @ if 0 its over
    addne r2,r2,#1                          @ else add 1 in the length
    bne 1b                                  @ and loop
                                            @ so here r2 contains the length of the message
    mov r1,r0                               @ address message in r1
    mov r0,#STDOUT                          @ code to write to the standard output Linux
    mov r7, #WRITE                          @ code call system "write"
    svc #0                                  @ call systeme
    pop {r0,r1,r2,r7,lr}                    @ restaur registers */
    bx lr                                   @ return
/******************************************************************/
/*     Converting a register to a decimal                                 */
/******************************************************************/
/* r0 contains value and r1 address area   */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                         @ save registers
    mov r3,r1
    mov r2,#LGZONECAL
1:                                          @ start loop
    bl divisionpar10                        @ r0 <- dividende. quotient ->r0 reste -> r1
    add r1,#48                              @ digit
    strb r1,[r3,r2]                         @ store digit on area
    cmp r0,#0                               @ stop if quotient = 0
    subne r2,#1                               @ previous position
    bne 1b                                  @ else loop
                                            @ end replaces digit in front of area
    mov r4,#0
2:
    ldrb r1,[r3,r2]
    strb r1,[r3,r4]                         @ store in area begin
    add r4,#1
    add r2,#1                               @ previous position
    cmp r2,#LGZONECAL                       @ end
    ble 2b                                  @ loop
    mov r1,#' '
3:
    strb r1,[r3,r4]
    add r4,#1
    cmp r4,#LGZONECAL                       @ end
    ble 3b
100:
    pop {r1-r4,lr}                          @ restaur registres
    bx lr                                   @return
/***************************************************/
/*   division par 10   signé                       */
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/*
/* and   http://www.hackersdelight.org/            */
/***************************************************/
/* r0 dividende   */
/* r0 quotient */
/* r1 remainder  */
divisionpar10:
  /* r0 contains the argument to be divided by 10 */
    push {r2-r4}                           @ save registers  */
    mov r4,r0
    mov r3,#0x6667                         @ r3 <- magic_number  lower
    movt r3,#0x6666                        @ r3 <- magic_number  upper
    smull r1, r2, r3, r0                   @ r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0)
    mov r2, r2, ASR #2                     @ r2 <- r2 >> 2
    mov r1, r0, LSR #31                    @ r1 <- r0 >> 31
    add r0, r2, r1                         @ r0 <- r2 + r1
    add r2,r0,r0, lsl #2                   @ r2 <- r0 * 5
    sub r1,r4,r2, lsl #1                   @ r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10)
    pop {r2-r4}
    bx lr                                  @ return

Create a simple DOM and serialize it into the specified XML format.


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

/* REMARK 1 : this program use routines in a include file
   see task Include a file language arm assembly
   for the routine affichageMess conversion10
   see at end of this program the instruction include */

/*******************************************/
/* Constantes                              */
/*******************************************/
.equ STDOUT, 1           @ Linux output console
.equ EXIT,   1           @ Linux syscall
.equ WRITE,  4           @ Linux syscall
.equ BRK,    0x2d        @ Linux syscall
.equ CHARPOS,     '@'

.equ GETTIME,   0x4e     @ call system linux gettimeofday

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

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessError:       .asciz "Error detected !!!!. \n"
szMessResult:      .asciz "GMT: @/@/@  @:@:@  @ms\n"  @ message result

szCarriageReturn:  .asciz "\n"
.align 4
tbDayMonthYear:    .int  0,  31,  60,  91, 121, 152, 182, 213, 244, 274, 305, 335
                   .int 366, 397, 425, 456, 486, 517, 547, 578, 609, 639, 670, 700
                   .int 731, 762, 790, 821, 851, 882, 912, 943, 974,1004,1035,1065
                   .int 1096,1127,1155,1186,1216,1247,1277,1308,1339,1369,1400,1430
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
stTVal:                .skip timeval_end
stTZone:               .skip timezone_end
sZoneConv:             .skip 100
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                              @ entry of program
    ldr r0,iAdrstTVal
    ldr r1,iAdrstTZone
    mov r7,#GETTIME
    svc 0
    cmp r0,#-1                     @ error ?
    beq 99f
    ldr r0,iAdrstTVal
    ldr r1,[r0,#timeval_sec]       @ timestemp in second
    //ldr r1,iTStest1
    //ldr r1,iTStest2
    //ldr r1,iTStest3
    ldr r2,iSecJan2020
    sub r0,r1,r2                   @ total secondes to 01/01/2020
    mov r1,#60
    bl division
    mov r0,r2
    mov r6,r3                      @ compute secondes
    mov r1,#60
    bl division
    mov r7,r3                      @ compute minutes
    mov r0,r2
    mov r1,#24
    bl division
    mov r8,r3                      @ compute hours
    mov r0,r2
    mov r11,r0
    mov r1,#(365 * 4 + 1)
    bl division
    lsl r9,r2,#2                   @ multiply by 4 = year1
    mov r1,#(365 * 4 + 1)
    mov r0,r11
    bl division
    mov r10,r3
    ldr r1,iAdrtbDayMonthYear
    mov r2,#3
    mov r3,#12
1:
    mul r11,r3,r2
    ldr r12,[r1,r11,lsl #2]         @ load days by year
    cmp r10,r12
    bge 2f
    sub r2,r2,#1
    cmp r2,#0
    bne 1b
2:                                 @ r2 = year2
    mov r5,#11
    mul r4,r3,r2
    lsl r4,#2
    add r4,r1
3:
    ldr r12,[r4,r5,lsl #2]         @ load days by month
    cmp r10,r12
    bge 4f
    subs r5,r5,#1
    bne 3b
4:                                 @ r5 = month - 1
    mul r11,r3,r2
    add r11,r5
    ldr r1,iAdrtbDayMonthYear
    ldr r3,[r1,r11,lsl #2]
    sub r0,r10,r3

    add r0,r0,#1                   @ final compute day
    ldr r1,iAdrsZoneConv
    bl conversion10                @ this function do not zero final
    mov r4,#0                      @ store zero final
    strb r4,[r1,r0]
    ldr r0,iAdrszMessResult
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at first @ character
    mov r3,r0
    add r0,r5,#1                   @ final compute month
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r4,#0                      @ store zero final
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at next @ character
    mov r3,r0
    ldr r11,iYearStart
    add r0,r9,r11
    add r0,r0,r2                   @ final compute year = 2020 + year1 + year2
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r4,#0                      @ store zero final
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at next @ character
    mov r3,r0
    mov r0,r8                      @ hours
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r4,#0                      @ store zero final
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at next @ character
    mov r3,r0
    mov r0,r7                      @ minutes
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r4,#0                      @ store zero final
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at next @ character
    mov r3,r0
    mov r0,r6                      @ secondes
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r4,#0                      @ store zero final
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at next @ character
    mov r3,r0
    ldr r1,iAdrstTVal
    ldr r0,[r1,#timeval_usec]      @ millisecondes
    ldr r1,iAdrsZoneConv
    bl conversion10
    mov r4,#0                      @ store zero final
    strb r4,[r1,r0]
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc          @ insert result at next @ character
    bl affichageMess
    b 100f
99:
    ldr r0,iAdrszMessError
    bl affichageMess
100:                               @ standard end of the program
    mov r0,#0                      @ return code
    mov r7,#EXIT                   @ request to exit program
    svc 0                          @ perform the system call

iAdrszMessError:          .int szMessError
iAdrstTVal:               .int stTVal
iAdrstTZone:              .int stTZone
iAdrszMessResult:         .int szMessResult
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrsZoneConv:            .int sZoneConv
iSecJan2020:              .int 1577836800
iAdrtbDayMonthYear:       .int tbDayMonthYear
iYearStart:               .int 2020
iTStest1:                 .int 1609508339    @ 01/01/2021
iTStest2:                 .int 1657805939    @ 14/07/2022
iTStest3:                 .int 1767221999    @ 31/12/2025
/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"

the system time in a specified unit. This can be used for debugging, network information, random number seeds, or program performance. The time is retrieved either by a system command or a built-in language function. It is related to the task of date formatting and retrieving system time.


ProgramStart:
	mov sp,#0x03000000			;Init Stack Pointer

	mov r4,#0x04000000  		        ;DISPCNT -LCD Control
	mov r2,#0x403    			;4= Layer 2 on / 3= ScreenMode 3
	str r2,[r4]         	                ;hardware specific routine, activates Game Boy's bitmap mode

	mov r0,#0x61				;ASCII "a"
	mov r2,#ramarea
	mov r1,#26

rep_inc_stosb:                                  ;repeatedly store a byte into memory, incrementing the destination and the value stored
                                                ;    each time.
	strB r0,[r2]
	add r0,r0,#1
	add r2,r2,#1
	subs r1,r1,#1
	bne rep_inc_stosb
	mov r0,#255
	strB r0,[r2]				;store a 255 terminator into r1

	mov r1,#ramarea
	bl PrintString                          ;Prints a 255-terminated string using a pre-defined bitmap font. Code omitted for brevity

forever:
        b forever                               ;halt the cpu

generate an array or list of all lower case ASCII characters from 'a' to 'z'. The code also demonstrates how to access a similar sequence from the standard library, if available. The coding style used is reliable and suitable for large programs, with strong typing implemented where possible. The code avoids manually enumerating all lowercase characters to prevent bugs. It also includes a feature to print the generated string of lower case ASCII characters to the screen. The code is written in VASM syntax and is designed for the Game Boy Advance hardware.


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

/* Constantes    */
.equ STDOUT, 1
.equ WRITE,  4
.equ EXIT,   1
/* Initialized data */
.data

sMessAffBin: .ascii "The decimal value  "
sZoneDec: .space 12,' '
             .ascii " should produce an output of "
sZoneBin: .space 36,' '
              .asciz "\n"

/*  code section */
.text
.global main
main:                /* entry of program  */
    push {fp,lr}    /* save des  2 registres */
    mov r0,#5
    ldr r1,iAdrsZoneDec
    bl conversion10S    @ decimal conversion
    bl conversion2      @ binary conversion and display résult
    mov r0,#50
    ldr r1,iAdrsZoneDec
    bl conversion10S
    bl conversion2
    mov r0,#-1
    ldr r1,iAdrsZoneDec
    bl conversion10S
    bl conversion2
    mov r0,#1
    ldr r1,iAdrsZoneDec
    bl conversion10S
    bl conversion2

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
iAdrsZoneDec: .int sZoneDec
/******************************************************************/
/*     register conversion in binary                              */
/******************************************************************/
/* r0 contains the register */
conversion2:
    push {r0,lr}     /* save  registers */
    push {r1-r5} /* save others registers */
    ldr r1,iAdrsZoneBin   @ address reception area
    clz r2,r0    @ number of left zeros bits
    rsb r2,#32   @ number of significant bits
    mov r4,#' '  @ space
    add r3,r2,#1 @ position counter in reception area
1:
    strb r4,[r1,r3]   @ space in other location of reception area
    add r3,#1
    cmp r3,#32         @ end of area ?
    ble 1b            @ no! loop
    mov r3,r2    @ position counter of the written character
2:               @ loop
    lsrs r0,#1    @ shift right one bit with flags
    movcc r4,#48  @ carry clear  => character 0
    movcs r4,#49  @ carry set   => character 1
    strb r4,[r1,r3]  @ character in reception area at position counter
    sub r3,r3,#1     @
    subs r2,r2,#1   @  0 bits ?
    bgt 2b          @ no!  loop

    ldr r0,iAdrsZoneMessBin
    bl affichageMess

100:
    pop {r1-r5}  /* restaur others registers */
    pop {r0,lr}
    bx lr
iAdrsZoneBin: .int sZoneBin
iAdrsZoneMessBin: .int sMessAffBin

/******************************************************************/
/*     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 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" */
    swi #0                      /* call systeme */
    pop {r0,r1,r2,r7}     		/* restaur others registres */
    pop {fp,lr}    				/* restaur des  2 registres */
    bx lr	        			/* return  */
/***************************************************/
/*   conversion registre en décimal   signé  */
/***************************************************/
/* r0 contient le registre   */
/* r1 contient l adresse de la zone de conversion */
conversion10S:
    push {fp,lr}    /* save des  2 registres frame et retour */
    push {r0-r5}   /* save autres registres  */
    mov r2,r1       /* debut zone stockage */
    mov r5,#'+'     /* par defaut le signe est + */
    cmp r0,#0       /* nombre négatif ? */
    movlt r5,#'-'     /* oui le signe est - */
    mvnlt r0,r0       /* et inversion en valeur positive */
    addlt r0,#1
    mov r4,#10   /* longueur de la zone */
1: /* debut de boucle de conversion */
    bl divisionpar10 /* division  */
    add r1,#48        /* ajout de 48 au reste pour conversion ascii */
    strb r1,[r2,r4]  /* stockage du byte en début de zone r5 + la position r4 */
    sub r4,r4,#1      /* position précedente */
    cmp r0,#0
    bne 1b	       /* boucle si quotient different de zéro */
    strb r5,[r2,r4]  /* stockage du signe à la position courante */
    subs r4,r4,#1   /* position précedente */
    blt  100f         /* si r4 < 0  fin  */
    /* sinon il faut completer le debut de la zone avec des blancs */
    mov r3,#' '   /* caractere espace */
2:
    strb r3,[r2,r4]  /* stockage du byte  */
    subs r4,r4,#1   /* position précedente */
    bge 2b        /* boucle si r4 plus grand ou egal a zero */
100:  /* fin standard de la fonction  */
    pop {r0-r5}   /*restaur des autres registres */
    pop {fp,lr}   /* restaur des  2 registres frame et retour  */
    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 others registers  */
    mov r4,r0
    ldr r3, .Ls_magic_number_10 /* r1 <- magic_number */
    smull r1, r2, r3, r0   /* r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0) */
    mov r2, r2, ASR #2     /* r2 <- r2 >> 2 */
    mov r1, r0, LSR #31    /* r1 <- r0 >> 31 */
    add r0, r2, r1         /* r0 <- r2 + r1 */
    add r2,r0,r0, lsl #2   /* r2 <- r0 * 5 */
    sub r1,r4,r2, lsl #1   /* r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10) */
    pop {r2-r4}
    bx lr                  /* leave function */
    .align 4
.Ls_magic_number_10: .word 0x66666667

generate a sequence of binary digits for a given non-negative integer. The output displays only the binary digits of each number, followed by a newline, without any whitespace, radix, sign markers, or leading zeros. The conversion can be achieved using built-in radix functions or a user-defined function.


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

/* compile with as         */
/* link with gcc and options -lX11 -L/usr/lpp/X11/lib   */

/********************************************/
/*Constantes                                */
/********************************************/
.equ STDOUT,              1     @ Linux output console
.equ EXIT,                1     @ Linux syscall
.equ WRITE,               4     @ Linux syscall
/* constantes X11 */
.equ KeyPressed,          2
.equ ButtonPress,         4
.equ MotionNotify,        6
.equ EnterNotify,         7
.equ LeaveNotify,         8
.equ Expose,              12
.equ ClientMessage,       33
.equ KeyPressMask,        1
.equ ButtonPressMask,     4
.equ ButtonReleaseMask,   8
.equ ExposureMask,        1<<15
.equ StructureNotifyMask, 1<<17
.equ EnterWindowMask,     1<<4
.equ LeaveWindowMask,     1<<5
.equ ConfigureNotify,     22

/*******************************************/
/* DONNEES INITIALISEES                    */
/*******************************************/
.data
szWindowName:            .asciz "Windows Raspberry"
szRetourligne:           .asciz  "\n"
szMessDebutPgm:          .asciz "Program start. \n"
szMessErreur:            .asciz "Server X not found.\n"
szMessErrfen:            .asciz "Can not create window.\n"
szMessErreurX11:         .asciz "Error call function X11. \n"
szMessErrGc:             .asciz "Can not create graphics context.\n"
szTitreFenRed:           .asciz "Pi"
szTexte1:                .asciz "<- red pixel is here !!"
.equ LGTEXTE1, . - szTexte1
szTexte2:                .asciz "Press q for close window or clic X in system menu."
.equ LGTEXTE2, . - szTexte2
szLibDW: .asciz "WM_DELETE_WINDOW"    @ special label for correct close error

/*************************************************/
szMessErr: .ascii	"Error code hexa : "
sHexa: .space 9,' '
         .ascii "  decimal :  "
sDeci: .space 15,' '
         .asciz "\n"

/*******************************************/
/* DONNEES NON INITIALISEES                    */
/*******************************************/
.bss
.align 4
ptDisplay:          .skip 4      @ pointer display
ptEcranDef:         .skip 4      @ pointer screen default
ptFenetre:          .skip 4      @ pointer window
ptGC:               .skip 4      @ pointer graphic context
ptGC1:              .skip 4      @ pointer graphic context1
key:                .skip 4      @ key code
wmDeleteMessage:    .skip 8      @ ident close message
event:              .skip 400    @ TODO event size ??
PrpNomFenetre:      .skip 100    @ window name proprety
buffer:             .skip 500
iWhite:             .skip 4      @ rgb code for white pixel
iBlack:             .skip 4      @ rgb code for black pixel
/**********************************************/
/* -- Code section                            */
/**********************************************/
.text
.global main

main:                               @ entry of program
    ldr r0,iAdrszMessDebutPgm   @
    bl affichageMess            @ display start message on console linux
    /* attention r6  pointer display*/
    /* attention r8  pointer graphic context   */
    /* attention r9 ident window  */
    /*****************************/
    /*    OPEN SERVER X11        */
    /*****************************/
    mov r0,#0
    bl XOpenDisplay             @ open X server
    cmp r0,#0                   @ error ?
    beq erreurServeur
    ldr r1,iAdrptDisplay
    str r0,[r1]                 @ store display address
    mov r6,r0                   @ and in register r6
    ldr r2,[r0,#+132]           @ load default_screen
    ldr r1,iAdrptEcranDef
    str r2,[r1]                 @ store default_screen
    mov r2,r0
    ldr r0,[r2,#+140]           @ load pointer screen list
    ldr r5,[r0,#+52]            @ load value white pixel
    ldr r4,iAdrWhite            @ and store in memory
    str r5,[r4]
    ldr r3,[r0,#+56]            @ load value black pixel
    ldr r4,iAdrBlack            @ and store in memory
    str r3,[r4]
    ldr r4,[r0,#+28]            @ load bits par pixel
    ldr r1,[r0,#+8]             @ load root windows
    /**************************/
    /* CREATE WINDOW          */
    /**************************/
    mov r0,r6                   @ address display
    mov r2,#0                   @ window position X
    mov r3,#0                   @ window position Y
    mov r8,#0                   @ for stack alignement
    push {r8}
    push {r3}                   @  background  = black pixel
    push {r5}                   @  border = white pixel
    mov r8,#2                   @  border size
    push {r8}
    mov r8,#240                 @ hauteur
    push {r8}
    mov r8,#320                 @ largeur
    push {r8}
    bl XCreateSimpleWindow
    add sp,#24                  @ stack alignement  6 push (4 bytes * 6)
    cmp r0,#0                   @ error ?
    beq erreurF

    ldr r1,iAdrptFenetre
    str r0,[r1]                 @ store window address in memory
    mov r9,r0                   @ and in register r9
    /*****************************/
    /* add window property       */
    /*****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    ldr r2,iAdrszWindowName     @ window name
    ldr r3,iAdrszTitreFenRed    @ window name reduced
    mov r4,#0
    push {r4}                   @ parameters not use
    push {r4}
    push {r4}
    push {r4}
    bl XSetStandardProperties
    add sp,sp,#16               @ stack alignement for 4 push
    /**************************************/
    /* for correction window close error  */
    /**************************************/
    mov r0,r6                   @ display address
    ldr r1,iAdrszLibDW          @ atom address
    mov r2,#1                   @ False  créate atom if not exists
    bl XInternAtom
    cmp r0,#0                   @ error X11 ?
    ble erreurX11
    ldr r1,iAdrwmDeleteMessage  @ recept address
    str r0,[r1]
    mov r2,r1                   @ return address
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r3,#1                   @ number of protocols
    bl XSetWMProtocols
    cmp r0,#0                   @ error X11 ?
    ble erreurX11
    /**********************************/
    /*  create graphic context        */
    /**********************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r2,#0                   @ not use for simply context
    mov r3,#0
    bl XCreateGC
    cmp r0,#0                   @ error ?
    beq erreurGC
    ldr r1,iAdrptGC
    str r0,[r1]                 @ store address graphic context
    mov r8,r0                   @ and in r8
    @ create other GC
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r2,#0                   @ not use for simply context
    mov r3,#0
    bl XCreateGC
    cmp r0,#0                   @ error ?
    beq erreurGC
    ldr r1,iAdrptGC1
    str r0,[r1]                 @ store address graphic context 1
    mov r1,r0
    mov r0,r6
    mov r2,#0xFF0000            @ color red
    bl XSetForeground
    cmp r0,#0
    beq erreurGC
    /****************************/
    /* modif window background  */
    /****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    ldr r2,iGris1               @ background color
    bl XSetWindowBackground
    cmp r0,#0                   @ error ?
    ble erreurX11
    /***************************/
    /* OUF!! window display    */
    /***************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    bl XMapWindow
    /****************************/
    /* Write text1 in the window */
    /****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r2,r8                   @ address graphic context
    mov r3,#105                 @ position x
    sub sp,#4                   @ stack alignement
    mov r4,#LGTEXTE1  - 1       @ size string
    push {r4}                   @ on the stack
    ldr r4,iAdrszTexte1         @ string address
    push {r4}
    mov r4,#105                 @ position y
    push {r4}
    bl XDrawString
    add sp,sp,#16               @ stack alignement 3 push and 1 stack alignement
    cmp r0,#0                   @ error ?
    blt erreurX11
    /****************************/
    /* Write text2 in the window */
    /****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    mov r2,r8                   @ address graphic context
    mov r3,#10                  @ position x
    sub sp,#4                   @ stack alignement
    mov r4,#LGTEXTE2  - 1       @ size string
    push {r4}                   @ on the stack
    ldr r4,iAdrszTexte2         @ string address
    push {r4}
    mov r4,#200                 @ position y
    push {r4}
    bl XDrawString
    add sp,sp,#16               @ stack alignement 3 push and 1 stack alignement
    cmp r0,#0                   @ error ?
    blt erreurX11
    /****************************************/
    /* draw pixel                           */
    /****************************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    ldr r2,iAdrptGC1
    ldr r2,[r2]                 @  address graphic context 1
    mov r3,#100                 @ position x
    sub sp,sp,#4                @ stack alignement
    mov r4,#100                 @ position y
    push {r4}                   @ on the stack
    bl XDrawPoint
    add sp,sp,#8                @ stack alignement 1 push and 1 stack alignement

    cmp r0,#0                   @ error ?
    blt erreurX11
    /****************************/
    /* Autorisations            */
    /****************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    ldr r2,iFenetreMask         @ autorisation mask
    bl XSelectInput
    cmp r0,#0                   @ error ?
    ble erreurX11
    /****************************/
    /* Events loop              */
    /****************************/
1:
    mov r0,r6                   @ display address
    ldr r1,iAdrevent            @ events address
    bl XNextEvent               @ event ?
    ldr r0,iAdrevent
    ldr r0,[r0]                 @ code event
    cmp r0,#KeyPressed          @ key ?
    bne 2f
    ldr r0,iAdrevent            @ yes read key in buffer
    ldr r1,iAdrbuffer
    mov r2,#255
    ldr r3,iAdrkey
    mov r4,#0
    push {r4}                   @ stack alignement
    push {r4}
    bl XLookupString
    add sp,#8                   @ stack alignement 2 push
    cmp r0,#1                   @ is character key ?
    bne 2f
    ldr r0,iAdrbuffer           @ yes -> load first buffer character
    ldrb r0,[r0]
    cmp r0,#0x71                @ character q for quit
    beq 5f                      @ yes -> end
    b 4f
2:
    /*                                  */
    /* for example  clic mouse button   */
    /************************************/
    cmp r0,#ButtonPress         @ clic mouse buton
    bne 3f
    ldr r0,iAdrevent
    ldr r1,[r0,#+32]            @ position X mouse clic
    ldr r2,[r0,#+36]            @ position Y
    @ etc for eventuel use
    b 4f
3:
    cmp r0,#ClientMessage       @ code for close window within error
    bne 4f
    ldr r0,iAdrevent
    ldr r1,[r0,#+28]            @ code message address
    ldr r2,iAdrwmDeleteMessage  @ equal code window créate ???
    ldr r2,[r2]
    cmp r1,r2
    beq 5f                      @ yes -> end window

4:  @ loop for other event
    b 1b
    /***********************************/
    /* Close window -> free ressources */
    /***********************************/
5:
    mov r0,r6                  @ display address
    ldr r1,iAdrptGC
    ldr r1,[r1]                @ load context graphic address
    bl XFreeGC
    cmp r0,#0
    blt erreurX11
    mov r0,r6                  @ display address
    mov r1,r9                  @ window address
    bl XDestroyWindow
    cmp r0,#0
    blt erreurX11
    mov r0,r6                  @ display address
    bl XCloseDisplay
    cmp r0,#0
    blt erreurX11
    mov r0,#0                  @ return code OK
    b 100f
erreurF:   @ create error window but possible not necessary. Display error by server
    ldr r1,iAdrszMessErrfen
    bl   displayError
    mov r0,#1                  @ return error code
    b 100f
erreurGC:                      @ error create graphic context
    ldr r1,iAdrszMessErrGc
    bl   displayError
    mov r0,#1
    b 100f
erreurX11:    @ erreur X11
    ldr r1,iAdrszMessErreurX11
    bl   displayError
    mov r0,#1
    b 100f
erreurServeur:                 @ error no found X11 server see doc putty and Xming
    ldr r1,iAdrszMessErreur
    bl   displayError
    mov r0,#1
    b 100f

100:                           @ standard end of the program
    mov r7, #EXIT
    svc 0
iFenetreMask:        .int  KeyPressMask|ButtonPressMask|StructureNotifyMask
iGris1:              .int 0xFFA0A0A0
iAdrWhite:           .int iWhite
iAdrBlack:           .int iBlack
iAdrptDisplay:       .int ptDisplay
iAdrptEcranDef:      .int ptEcranDef
iAdrptFenetre:       .int ptFenetre
iAdrptGC:            .int ptGC
iAdrptGC1:           .int ptGC1
iAdrevent:           .int event
iAdrbuffer:          .int buffer
iAdrkey:             .int key
iAdrszLibDW:         .int szLibDW
iAdrszMessDebutPgm:  .int szMessDebutPgm
iAdrszMessErreurX11: .int szMessErreurX11
iAdrszMessErrGc:     .int szMessErrGc
iAdrszMessErreur:    .int szMessErreur
iAdrszMessErrfen:    .int szMessErrfen
iAdrszWindowName:    .int szWindowName
iAdrszTitreFenRed:   .int szTitreFenRed
iAdrszTexte1:            .int szTexte1
iAdrszTexte2:        .int szTexte2
iAdrPrpNomFenetre:   .int PrpNomFenetre
iAdrwmDeleteMessage: .int wmDeleteMessage

/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                   @ save  registres
    mov r2,#0                               @ counter length
1:                                          @ loop length calculation
    ldrb r1,[r0,r2]                         @ read octet start position + index
    cmp r1,#0                               @ if 0 its over
    addne r2,r2,#1                          @ else add 1 in the length
    bne 1b                                  @ and loop
                                            @ so here r2 contains the length of the message
    mov r1,r0                               @ address message in r1
    mov r0,#STDOUT                          @ code to write to the standard output Linux
    mov r7, #WRITE                          @ code call system "write"
    svc #0                                  @ call systeme
    pop {r0,r1,r2,r7,lr}                    @ restaur registers
    bx lr                                   @ return
/***************************************************/
/*   display error message                         */
/***************************************************/
/* r0 contains error code  r1 : message address */
displayError:
    push {r0-r2,lr}                         @ save registers
    mov r2,r0                               @ save error code
    mov r0,r1
    bl affichageMess
    mov r0,r2                               @ error code
    ldr r1,iAdrsHexa
    bl conversion16                         @ conversion hexa
    mov r0,r2                               @ error code
    ldr r1,iAdrsDeci                        @ result address
    bl conversion10                         @ conversion decimale
    ldr r0,iAdrszMessErr                    @ display error message
    bl affichageMess
100:
    pop {r0-r2,lr}                          @ restaur registers
    bx lr                                   @ return
iAdrszMessErr:                 .int szMessErr
iAdrsHexa:                     .int sHexa
iAdrsDeci:                     .int sDeci
/******************************************************************/
/*     Converting a register to hexadecimal                      */
/******************************************************************/
/* r0 contains value and r1 address area   */
conversion16:
    push {r1-r4,lr}                                    @ save registers
    mov r2,#28                                         @ start bit position
    mov r4,#0xF0000000                                 @ mask
    mov r3,r0                                          @ save entry value
1:                                                     @ start loop
    and r0,r3,r4                                       @value register and mask
    lsr r0,r2                                          @ move right
    cmp r0,#10                                         @ compare value
    addlt r0,#48                                       @ <10  ->digit
    addge r0,#55                                       @ >10  ->letter A-F
    strb r0,[r1],#1                                    @ store digit on area and + 1 in area address
    lsr r4,#4                                          @ shift mask 4 positions
    subs r2,#4                                         @  counter bits - 4 <= zero  ?
    bge 1b                                             @  no -> loop

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

"Creates a 320x240 window and draws a single red pixel at position (100, 100)."


.text
.global _start
_start:
    ldr r0, =example_numbers
    bl test_number

    add r1, r0, #1
    bl length
    add r0, r1, r0
    bl test_number

    add r1, r0, #1
    bl length
    add r0, r1, r0
    bl test_number

    add r1, r0, #1
    bl length
    add r0, r1, r0
    bl test_number

    mov r0, #0
    mov r7, #1
    swi 0

test_number:
    push {r0, lr}
    bl print_string

    bl luhn_test
    cmp r0, #1
    ldreq r0, =valid_message
    ldrne r0, =invalid_message
    bl print_string
    pop {r0, lr}
    mov pc, lr

print_string:
    push {r0-r7, lr}
    mov r1, r0   @ string to print
    bl length
    mov r2, r0   @ length of string
    mov r0, #1   @ write to stdout
    mov r7, #4   @ SYS_WRITE
    swi 0        @ call system interupt
    pop {r0-r7, lr}
    mov pc, lr

@ r0 address of credit card number string
@ returns result in r0
luhn_test:
    push {r1-r7, lr}
    mov r1, r0
    bl isNumerical            @ check if string is a number
    cmp r0, #1
    bne .luhn_test_end        @ exit if not number
    mov r0, r1
    ldr r1, =reversed_string  @ address to store reversed string
    bl reverse                @ reverse string
    push {r0}
    bl length   @ get length of string
    mov r4, r0  @ store string length in r4
    pop {r0}
    mov r2, #0  @ string index
    mov r6, #0  @ sum of odd digits
    mov r7, #0  @ sum of even digits
    .loadNext:
        ldrb r3, [r1, r2]         @ load byte into r3
        sub r3, #'0'              @ convert letter to digit
        and r5, r2, #1            @ test if index is even or odd
        cmp r5, #0
        beq .odd_digit
        bne .even_digit
        .odd_digit:
            add r6, r3              @ add digit to sum if odd
            b .continue             @ skip next step
        .even_digit:
            lsl r3, #1              @ multiply digit by 2
            cmp r3, #10             @ sum digits
            subge r3, #10           @ get digit in 1s place
            addge r3, #1            @ add 1 for the 10s place
            add r7, r3              @ add digit sum to the total

        .continue:
        add r2, #1                @ increment digit index
        cmp r2, r4                @ check if at end of string
        blt .loadNext

    add r0, r6, r7                @ add even and odd sum
    mov r3, r0                    @ copy sum to r3
    ldr r1, =429496730            @ (2^32-1)/10
    sub r0, r0, r0, lsr #30       @ divide by 10
    umull r2, r0, r1, r0
    mov r1, #10
    mul r0, r1                    @ multiply the r0 by 10 to see if divisible
    cmp r0, r3                    @ compare with the original value in r3
    .luhn_test_end:
    movne r0, #0                  @ return false if invalid card number
    moveq r0, #1                  @ return true if valid card number
    pop {r1-r7, lr}
    mov pc, lr

length:
    push {r1-r2, lr}
    mov r2, r0              @ start of string address
    .loop:
        ldrb r1, [r2], #1   @ load byte from address r2 and increment
        cmp r1, #0          @ check for end of string
        bne .loop           @ load next byte if not 0
    sub r0, r2, r0          @ subtract end of string address from start
    sub r0, #1              @ end of line from count
    pop {r1-r2, lr}
    mov pc, lr

@ reverses a string
@ r0 address of string to reverse
@ r1 address to store reversed string
reverse:
    push {r0-r5, lr}
    push {r0, lr}
    bl length                @ get length of string to reverse
    mov r3, r0               @ backword index
    pop {r0, lr}
    mov r4, #0               @ fowrard index
    .reverse_next:
        sub r3, #1           @ decrement backword index
        ldrb r5, [r0, r3]    @ load byte from original string at index
        strb r5, [r1, r4]    @ copy byte to reversed string
        add r4, #1           @ increment fowrard index
        cmp r3, #0           @ check if any characters are left
        bge .reverse_next

    mov r5, #0
    strb r5, [r1, r4]  @ write null byte to terminate reversed string
    pop {r0-r5, lr}
    mov pc, lr

isNumerical:
    push {r1, lr}
    .isNumerical_checkNext:
        ldrb r1, [r0], #1
        cmp r1, #0
        beq .isNumerical_true
        cmp r1, #'0'
        blt .isNumerical_false
        cmp r1, #'9'
        bgt .isNumerical_false
        b .isNumerical_checkNext
    .isNumerical_false:
        mov r0, #0
        b .isNumerical_end
    .isNumerical_true:
        mov r0, #1
    .isNumerical_end:
    pop {r1, lr}
    mov pc, lr

.data
valid_message:
    .asciz " valid card number\n"
invalid_message:
    .asciz " invalid card number\n"

reversed_string:
    .space 32

example_numbers:
    .asciz "49927398716"
    .asciz "49927398717"
    .asciz "1234567812345678"
    .asciz "1234567812345670"

The code validates credit card numbers using the Luhn test. It reverses the input number, calculates the sum of odd and even positioned digits (with even digits being doubled and if the result is greater than nine, the digits of the result are summed). If the total sum ends in zero, the number is deemed valid. The code tests this functionality on four given numbers.


Works with: as version Raspberry Pi
/* ARM assembly AARCH64 Raspberry PI 3B */
/* ARM assembly Raspberry PI  */
/*  program josephus.s   */

/* REMARK 1 : this program use routines in a include file
   see task Include a file language arm assembly
   for the routine affichageMess conversion10
   see at end of this program the instruction include */

/*******************************************/
/* Constantes                              */
/*******************************************/
.equ STDOUT, 1           @ Linux output console
.equ EXIT,   1           @ Linux syscall
.equ WRITE,  4           @ Linux syscall
.equ BRK,    0x2d        @ Linux syscall
.equ CHARPOS,     '@'

.equ FIRSTNODE,        0              //identification first node

/*******************************************/
/* 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
szMessDebutPgm:          .asciz "Start program.\n"
szMessFinPgm:            .asciz "Program End ok.\n"
szRetourLigne:            .asciz "\n"
szMessValElement:        .asciz "Value : @ \n"
szMessListeVide:         .asciz "List empty.\n"
szMessImpElement:        .asciz "Node display: @ Value : @ Next @ \n"
szMessErrComm:           .asciz "Incomplete Command line  : josephus <maxi> <intervalle>\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:         .skip 24
.align 4
qDebutListe1:      .skip llist_fin
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                   // entry of program
    mov fp,sp                           // copy stack address  register r29 fp
    ldr r0,iAdrszMessDebutPgm
    bl affichageMess
    ldr r0,[fp]                        // parameter number command line
    cmp r0,#2                          // correct ?
    ble erreurCommande                 // error

    add r0,fp,#8                       // address parameter 2
    ldr r0,[r0]
    bl conversionAtoD
    add r2,r0,#FIRSTNODE               // save maxi
    add r0,fp,#12                      // address parameter 3
    ldr r0,[r0]
    bl conversionAtoD
    mov r8,r0                          // save gap

    mov r0,#FIRSTNODE                  // create first node
    mov r1,#0
    bl createNode
    mov r5,r0                          // first node address
    mov r6,r0
    mov r4,#FIRSTNODE + 1
    mov r3,#1
1:                                     // loop create others nodes
    mov r0,r4                          // key value
    mov r1,#0
    bl createNode
    str r0,[r6,#llist_next]             // store current node address in prev node
    mov r6,r0
    add r4,r4,#1
    add r3,r3,#1
    cmp r3,r2                          // maxi ?
    blt 1b
    str r5,[r6,#llist_next]            // store first node address in last pointer
    mov r4,r6
2:
    mov r2,#1                          // counter for gap
3:
    ldr r4,[r4,#llist_next]
    add r2,r2,#1
    cmp r2,r8                          // intervalle ?
    blt 3b
    ldr r5,[r4,#llist_next]            // removing the node from the list
    ldr r2,[r5,#llist_value]
    ldr r7,[r5,#llist_next]            // load pointer next
    str r7,[r4,#llist_next]            // ans store in prev node
    //mov r0,r25
    //bl displayNode
    cmp r7,r4
    moveq r4,r7
    bne 2b                              // and loop

    mov r0,r4
    bl displayNode                      // display last node

    b 100f
erreurCommande:
    ldr r0,iAdrszMessErrComm
    bl affichageMess
    mov r0,#1                          // error code
    b 100f
100:                                   // program end standard
    ldr r0,iAdrszMessFinPgm
    bl affichageMess
    mov r0,#0                          // return code Ok
    mov r7,#EXIT                       // system call "Exit"
    svc #0

iAdrszMessDebutPgm:      .int szMessDebutPgm
iAdrszMessFinPgm:        .int szMessFinPgm
iAdrszRetourLigne:       .int szRetourLigne
iAdrqDebutListe1:        .int qDebutListe1
iAdrszMessErrComm:       .int szMessErrComm

/******************************************************************/
/*     create node                                             */
/******************************************************************/
/* r0 contains key   */
/* r1 contains zero or address next node */
/* r0 returns address heap node  */
createNode:
    push {r1-r11,lr}            // save  registers
    mov r9,r0                   // save key
    mov r10,r1                  // save key
    mov r0,#0                   // allocation place heap
    mov r7,#BRK                 // call system 'brk'
    svc #0
    mov r11,r0                  // save address heap for node
    add r0,r0,#llist_fin        // reservation place node length
    mov r7,#BRK                 // call system 'brk'
    svc #0
    cmp r0,#-1                  // allocation error
    beq 100f

    str r9,[r11,#llist_value]
    str r10,[r11,#llist_next]
    mov r0,r11
100:
    pop {r1-r11,lr}            // restaur registers
    bx lr                      // return

/******************************************************************/
/*     display infos node                                     */
/******************************************************************/
/* r0 contains node address */
displayNode:
    push {r1-r4,lr}           // save  registers
    mov r2,r0
    ldr r1,iAdrsZoneConv
    bl conversion16
    mov r4,#0
    strb r4,[r1,r0]           // store zero final
    ldr r0,iAdrszMessImpElement
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#llist_value]
    ldr r1,iAdrsZoneConv
    bl conversion10S
    mov r4,#0
    strb r4,[r1,r0]           // store zero final
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    mov r3,r0
    ldr r0,[r2,#llist_next]
    ldr r1,iAdrsZoneConv
    bl conversion16
    mov r4,#0
    strb r4,[r1,#8]           // store zero final
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl strInsertAtCharInc
    bl affichageMess

100:
    pop {r1-r4,lr}            // restaur registers
    bx lr                     // return
iAdrsZoneConv:               .int sZoneConv
iAdrszMessImpElement:        .int szMessImpElement
/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"
pi@raspberrypi:~/asm32/rosetta32/ass6 $ josephus 41 3
Start program.
Node display: 00F880F0 Value :         +30 Next 00F880F0
Program End ok.

- Determine the final survivor in the Josephus problem given any number of prisoners (n) and a step count (k).
- Calculate the position of any prisoner in the killing sequence.
- Provide an option to save a certain number of prisoners (m).
- The numbering of prisoners can start from either 0 or 1.
- The complexity of the solution is O(kn) for the complete killing sequence and O(m) for finding the m-th prisoner to die.