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

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

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

1:
    ldr r0,iAdrTableNumber                        @ address number table
    mov r1,#0                                     @ not use in routine
    mov r2,#NBELEMENTS                            @ number of élements
    bl shellSort
    ldr r0,iAdrTableNumber                        @ address number table
    bl displayTable

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

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

/* r0 contains the address of table */
/* r1 contains the first element but not use !!   */
/*   this routine use first element at index zero !!!  */
/* r2 contains the number of element */
shellSort:
    push {r0-r7,lr}              @save registers

    sub r2,#1                    @ index last item
    mov r1,r2                    @ init gap = last item
1:                               @ start loop 1
    lsrs r1,#1                   @ gap = gap / 2
    beq 100f                     @ if gap = 0 -> end
    mov r3,r1                    @ init loop indice 1
2:                               @ start loop 2
    ldr r4,[r0,r3,lsl #2]        @ load first value
    mov r5,r3                    @ init loop indice 2
3:                               @ start loop 3
    cmp r5,r1                    @ indice < gap
    blt 4f                       @ yes -> end loop 2
    sub r6,r5,r1                 @ index = indice - gap
    ldr r7,[r0,r6,lsl #2]        @ load second value
    cmp r4,r7                    @ compare values
    strlt r7,[r0,r5,lsl #2]      @ store if <
    sublt r5,r1                  @ indice = indice - gap
    blt 3b                       @ and loop
4:                               @ end loop 3
    str r4,[r0,r5,lsl #2]        @ store value 1 at indice 2
    add r3,#1                    @ increment indice 1
    cmp r3,r2                    @ end ?
    ble 2b                       @ no -> loop 2
    b 1b                         @ yes loop for new gap

100:                             @ end function
    pop {r0-r7,lr}               @ restaur registers
    bx lr                        @ return

/******************************************************************/
/*      Display table elements                                */
/******************************************************************/
/* r0 contains the address of table */
displayTable:
    push {r0-r3,lr}                                    @ save registers
    mov r2,r0                                          @ table address
    mov r3,#0
1:                                                     @ loop display table
    ldr r0,[r2,r3,lsl #2]
    ldr r1,iAdrsMessValeur                             @ display value
    bl conversion10                                    @ call function
    ldr r0,iAdrsMessResult
    bl affichageMess                                   @ display message
    add r3,#1
    cmp r3,#NBELEMENTS - 1
    ble 1b
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
100:
    pop {r0-r3,lr}
    bx lr
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                          @ save  registres
    mov r2,#0                                      @ counter length
1:                                                 @ loop length calculation
    ldrb r1,[r0,r2]                                @ read octet start position + index
    cmp r1,#0                                      @ if 0 its over
    addne r2,r2,#1                                 @ else add 1 in the length
    bne 1b                                         @ and loop
                                                   @ so here r2 contains the length of the message
    mov r1,r0                                      @ address message in r1
    mov r0,#STDOUT                                 @ code to write to the standard output Linux
    mov r7, #WRITE                                 @ code call system "write"
    svc #0                                         @ call systeme
    pop {r0,r1,r2,r7,lr}                           @ restaur des  2 registres */
    bx lr                                          @ return
/******************************************************************/
/*     Converting a register to a decimal unsigned                */
/******************************************************************/
/* r0 contains value and r1 address area   */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes          */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                                 @ save registers
    mov r3,r1
    mov r2,#LGZONECAL

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

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

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

implement the Shell sort algorithm to sort an array of elements. This algorithm, invented by Donald Shell, uses a diminishing increment sort and interleaved insertion sorts based on an increment sequence. The increment size reduces after each pass until it reaches 1, turning the sort into a basic insertion sort. The data is almost sorted at this point, providing the best case for insertion sort. The increment sequence can vary but should always end in 1. Sequences with a geometric increment ratio of about 2.2 have been found to work well.


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

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

/* REMARK: This program was written for android with the termux app.
 It works very well on raspberry pi but in this case the memory access relocation instructions
 can be simplified.
*/

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

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

.equ GCForeground,        1<<2
.equ GCFont,              1<<14

/* constantes program */
.equ WINDOWWIDTH,       400
.equ WINDOWHEIGHT,      300

/*******************************************/
/* 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"
szMessErrFont:           .asciz "Font not found.\n"
szTitreFenRed:           .asciz "Pi"
szTexte1:                .asciz "Hello world!  "
.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

szfontname: .asciz  "-*-helvetica-bold-*-normal-*-12-*"         @ for font test
szfontname2: .asciz "-*-fixed-*-*-*-*-13-*-*-*-*-*"
.align 4
stXGCValues:       .int 0,0,0xFFA0A0A0,0,0,0,0,0,0,0,0,0,0,0,0,0,0   @ for foreground color gris1
//stXGCValues:       .int 0,0,0x00000000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0   @ for foreground color black
stXGCValues1:      .int 0,0,0x00FFFFFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0   @ for foreground color white
stXGCValues2:      .int 0,0,0x0000FF00,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0   @ for foreground color green
/*******************************************/
/* 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 context
ptFont:             .skip 4      @ pointer font
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
sbuffer1:             .skip 500
iWhite:             .skip 4      @ rgb code for white pixel
iBlack:             .skip 4      @ rgb code for black pixel
iSens:              .skip 4      @ direction of travel
/**********************************************/
/* -- Code section                            */
/**********************************************/
.text
.global main
iOfWhite:           .int iWhite - .
iOfBlack:           .int iBlack - .
iOfszMessDebutPgm:  .int szMessDebutPgm - .
iOfptDisplay:       .int ptDisplay - .
iOfptEcranDef:      .int ptEcranDef - .
iOfszLibDW:         .int szLibDW - .
main:                           @ entry of program
    adr r0,iOfszMessDebutPgm   @
    ldr r1,[r0]
    add r0,r1
    bl affichageMess            @ display start message on console linux
    /* attention r6  pointer display*/
    /* attention r8  pointer graphic context 1  */
    /* attention r9 ident window  */
    /* attention r10  pointer graphic context 2  */
    /*****************************/
    /*    OPEN SERVER X11        */
    /*****************************/
    mov r0,#0
    bl XOpenDisplay             @ open X server
    cmp r0,#0                   @ error ?
    beq erreurServeur
    adr r2,iOfptDisplay
    ldr r1,[r2]
    add r1,r2
    str r0,[r1]                 @ store display address

    mov r6,r0                   @ and in register r6
    ldr r2,[r0,#+132]           @ load default_screen
    adr r1,iOfptEcranDef
    ldr r3,[r1]
    add r1,r3
    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
    adr r4,iOfWhite             @ and store in memory
    ldr r3,[r4]
    add r4,r3
    str r5,[r4]
    ldr r7,[r0,#+56]            @ load value black pixel
    adr r4,iOfBlack             @ and store in memory
    ldr r5,[r4]
    add r4,r5
    str r7,[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 {r7}                   @  background  = black pixel
    push {r5}                   @  border = white pixel
    mov r8,#2                   @  border size
    push {r8}
    mov r8,#WINDOWHEIGHT        @ height
    push {r8}
    mov r8,#WINDOWWIDTH         @ width
    push {r8}
    bl XCreateSimpleWindow
    add sp,#24                  @ stack alignement  6 push (4 bytes * 6)
    cmp r0,#0                   @ error ?
    beq erreurF

    adr r1,iOfptFenetre
    ldr r3,[r1]
    add r1,r3
    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
    adr r2,iOfszWindowName      @ window name
    ldr r5,[r2]
    add r2,r5
    adr r3,iOfszTitreFenRed     @ window name reduced
    ldr r5,[r3]
    add r3,r5
    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
    adr r1,iOfszLibDW           @ atom address
    ldr r5,[r1]
    add r1,r5
    mov r2,#1                   @ False  créate atom if not exists
    bl XInternAtom
    cmp r0,#0                   @ error X11 ?
    blt erreurX11               @ Modif avril 22 pour android (ble pour raspberry)
    adr r1,iOfwmDeleteMessage  @ recept address
    ldr r5,[r1]
    add r1,r5
    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
    /***********************************/
    /* load font                       */
    /* remark : see font list X11 on your system */
    /***********************************/
    mov r0,r6                   @ display address
    bl loadFont

    /**********************************/
    /*  create graphic context        */
    /**********************************/
    mov r0,r6                   @ display address
    mov r1,r9                   @ window address
    bl createContextGraphic

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

                                @ copy text in buffer
    adr r0,iOfszTexte1          @ string address
    ldr r5,[r0]
    add r0,r5
    adr r1,iOfsbuffer1          @ buffer address
    ldr r5,[r1]
    add r1,r5
    mov r2,#0
1:                              @ loop copy character
    ldrb r3,[r0,r2]
    strb r3,[r1,r2]
    cmp r3,#0
    addne r2,r2,#1
    bne 1b

    /****************************/
    /* 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
    bl XPending                 @ loading the number of events
    cmp r0,#0
    bne 2f                      @ a event is occurring
    adr r3,iOfsbuffer1
    ldr r5,[r3]
    add r3,r5
    mov r0,r6                   @ display address
    mov r1,r9                   @ window ident
    mov r2,r8                   @ graphic context
    bl animate                  @ string display and move
    b 1b
2:
    mov r0,r6                   @ display address
    adr r1,iOfevent             @ events address
    ldr r5,[r1]
    add r1,r5
    bl XNextEvent               @ event ?
    adr r0,iOfevent
    ldr r5,[r0]
    add r0,r5
    ldr r0,[r0]                 @ code event
    cmp r0,#KeyPressed          @ key ?
    bne 2f
    adr r0,iOfevent            @ yes read key in buffer
    ldr r5,[r0]
    add r0,r5
    adr r1,iOfbuffer
    ldr r5,[r1]
    add r1,r5
    mov r2,#255
    adr r3,iOfkey
    ldr r5,[r3]
    add r3,r5
    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
    adr r0,iOfbuffer           @ yes -> load first buffer character
    ldr r5,[r0]
    add r0,r5
    ldrb r0,[r0]
    cmp r0,#0x71                @ character q for quit
    beq 5f                      @ yes -> end
    b 4f
2:
    /************************************/
    /*  clic mouse button   */
    /************************************/
    cmp r0,#ButtonPress         @ clic mouse buton
    bne 3f
    adr r0,iOfevent
    ldr r5,[r0]
    add r0,r5
    ldr r1,[r0,#+32]            @ position X mouse clic
    ldr r2,[r0,#+36]            @ position Y
    cmp r1,#50                  @ test if position clic is on the screen string approx.
    blt 4f
    cmp r1,#150
    bgt 4f
    cmp r2,#80
    blt 4f
    cmp r2,#105
    bgt 4f
    adr r1,iOfiSens             @ load direction
    ldr r2,[r1]
    add r1,r2
    ldr r2,[r1]
    cmp r2,#0                   @ direction inversion
    moveq r2,#1
    movne r2,#0
    str r2,[r1]
    b 4f
3:
    cmp r0,#ClientMessage       @ code for close window within error
    bne 4f
    adr r0,iOfevent
    ldr r5,[r0]
    add r0,r5
    ldr r1,[r0,#+28]            @ code message address
    adr r2,iOfwmDeleteMessage   @ equal code window créate ???
    ldr r5,[r2]
    add r2,r5
    ldr r2,[r2]
    cmp r1,r2
    beq 5f                      @ yes -> end window

4:  @ loop for other event
    b 1b
iOfptFenetre:       .int ptFenetre - .
iOfszWindowName:    .int szWindowName - .
iOfszTitreFenRed:   .int szTitreFenRed - .
    /***********************************/
    /* Close window -> free ressources */
    /***********************************/
5:
    mov r0,r6                  @ display address
    adr r1,iOfptGC
    ldr r5,[r1]
    add r1,r5
    ldr r1,[r1]                @ load context graphic address
    bl XFreeGC
    mov r0,r6                  @ display address
    adr r1,iOfptGC1
    ldr r5,[r1]
    add r1,r5
    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
    adr r1,iOfszMessErrfen
    ldr r5,[r1]
    add r1,r5
    bl   displayError
    mov r0,#1                  @ return error code
    b 100f
erreurGC:                      @ error create graphic context
    adr r1,iOfszMessErrGc
    ldr r5,[r1]
    add r1,r5
    bl   displayError
    mov r0,#1
    b 100f
erreurX11:    @ erreur X11
    adr r1,iOfszMessErreurX11
    ldr r5,[r1]
    add r1,r5
    bl   displayError
    mov r0,#1
    b 100f
erreurServeur:                 @ error no found X11 server see doc putty and Xming
    adr r1,iOfszMessErreur
    ldr r5,[r1]
    add r1,r5
    bl   displayError
    mov r0,#1
    b 100f

100:                           @ standard end of the program
    mov r7, #EXIT
    svc 0

iOfevent:           .int event - .
iOfbuffer:          .int buffer - .
iOfsbuffer1:        .int sbuffer1 - .
iOfkey:             .int key - .
iOfszMessErreurX11: .int szMessErreurX11 - .
iOfszMessErreur:    .int szMessErreur - .
iOfszMessErrfen:    .int szMessErrfen - .
iOfszTexte1:        .int szTexte1 - .
iOfszTexte2:        .int szTexte2 - .
iOfPrpNomFenetre:   .int PrpNomFenetre - .
iOfwmDeleteMessage: .int wmDeleteMessage - .

iFenetreMask:        .int  KeyPressMask|ButtonPressMask|StructureNotifyMask
iGris1:              .int 0xFFA0A0A0
iOfiSens:            .int iSens - .
/******************************************************************/
/*    load font                                                  */
/******************************************************************/
/* r0 contains display  */
loadFont:
    push {r1-r2,lr}           @ save  registers
    adr r1,iOfszfontname       @ font name
    ldr r2,[r1]
    add r1,r2
    bl XLoadQueryFont
    cmp r0,#0
    beq 99f                    @ font not find
    adr r1,iOfptFont
    ldr r2,[r1]
    add r1,r2
    str r0,[r1]
    mov r0,#0
    b 100f
99:
    adr r1,iOfszMessErrFont
    ldr r5,[r1]
    add r1,r5
    bl   displayError
    mov r0,#1
100:
    pop {r1-r2,pc}             @ restaur registers
iOfszfontname:          .int szfontname2 - .
iOfptFont:              .int ptFont - .
iOfszMessErrFont:       .int szMessErrFont - .
/******************************************************************/
/*    Context Graphic création                                                  */
/******************************************************************/
/* r0 contains display  */
/* r1 window address */
/* REMARKS : no standard use registers  return GC1 in r8 and GC2 in r10 */
createContextGraphic:
    push {r1-r7,lr}             @ save  registers
    /**********************************/
    /*  create graphic context        */
    /**********************************/
    mov r6,r0                   @ save display address
    mov r7,r1                   @ save window address
    adr r3,iOfptFont            @ font pointer
    ldr r1,[r3]
    add r3,r1
    ldr r3,[r3]
    ldr r4,[r3,#4]              @ load font ident
    adr r3,iOfstXGCValues2      @ green color in foreground
    ldr r5,[r3]
    add r3,r5                   @ this parameter is used by XcreateGC
    str r4,[r3,#60]             @ store ident font in  offset 60
    mov r0,r4
    mov r0,r6                   @ display address
    mov r1,r7                   @ window address
    mov r2,#GCForeground|GCFont @  @ green color in foreground and font
    bl XCreateGC
    cmp r0,#0                   @ error ?
    beq 99f
    adr r1,iOfptGC
    ldr r5,[r1]
    add r1,r5
    str r0,[r1]                 @ store address graphic context
    mov r8,r0                   @ and in r8
    /**********************************/
    /*  create 2 graphic context        */
    /**********************************/
    mov r0,r6                   @ display address
    mov r1,r7                   @ window address
    mov r2,#GCForeground        @ red color in Foreground
    adr r3,iOfstXGCValues
    ldr r5,[r3]
    add r3,r5
    bl XCreateGC
    cmp r0,#0                   @ error ?
    beq erreurGC
    adr r1,iOfptGC1
    ldr r5,[r1]
    add r1,r5
    str r0,[r1]                 @ store address graphic context
    mov r10,r0                  @ and in r10
    b 100f
99:                            @ create error
    adr r1,iOfszMessErrGc
    ldr r5,[r1]
    add r1,r5
    bl   displayError
    mov r0,#1
100:
    pop {r1-r7,pc}             @ restaur registers
iOfszMessErrGc:     .int szMessErrGc - .
iOfptGC:            .int ptGC - .
iOfptGC1:           .int ptGC1 - .
iOfstXGCValues:     .int stXGCValues - .
iOfstXGCValues1:     .int stXGCValues1 - .
iOfstXGCValues2:     .int stXGCValues2 - .
/******************************************************************/
/*    animation                                                   */
/******************************************************************/
/* r0 contains display  */
/* r1 contains window ident */
/* r2 contains context graphic */
/* r3 string address   */
animate:
    push {r2-r9,lr}            @ save  registers
    mov r5,r3                   @ save string address
    mov r6,r0                   @ save display
    mov r7,r1                   @ save window
    mov r8,r2                   @ save GC
                                @ erase text in the windows
    mov r0,r6                   @ display address
    mov r1,r7                   @ window ident
    mov r2,r10                  @ graphic context
    mov r3,#50                  @ position x
    mov r4,#LGTEXTE1  - 1       @ string lenght
    push {r4}                   @ stack alignement
    push {r4}                   @ to stack parameter

    push {r5}                   @ string address
    mov r4,#100                 @ position y
    push {r4}
    bl XDrawString
    add sp,sp,#16               @ stack alignement (4 push)

    mov r0,#LGTEXTE1 -2         @ string length
    adr r1,iOfiSens             @ load direction
    ldr r2,[r1]
    add r1,r2
    ldr r2,[r1]
    cmp r2,#0                   @ test direction
    bne 2f

    ldrb r9,[r5,r0]             @ last character
    sub r1,r0,#1
1:                              @ loop to move character one position
    ldrb r2,[r5,r1]
    strb r2,[r5,r0]
    sub r0,r0,#1
    subs r1,r1,#1
    bge 1b
    add r1,r1,#1
    strb r9,[r5,r1]             @ last character -> first character
    b 4f
2:
    ldrb r9,[r5]                @ first character
    mov r1,#1
    sub r2,r1,#1
3:                              @ loop to move character
    ldrb r3,[r5,r1]
    strb r3,[r5,r2]
    add r2,r2,#1
    add r1,r1,#1
    cmp r1,r0
    ble 3b
    strb r9,[r5,r2]             @ first character -> last character

4:
                                @ write text in the windows
    mov r0,r6                   @ display address
    mov r1,r7                   @ window ident
    mov r2,r8                   @ graphic context
    mov r3,#50                  @ position x
    mov r4,#LGTEXTE1  - 1       @ string lenght
    push {r4}                   @ stack alignement
    push {r4}                   @ to stack parameter
    push {r5}                   @ string address
    mov r4,#100                 @ position y
    push {r4}
    bl XDrawString
    add sp,sp,#16               @ stack alignement (4 push)
    mov r0,#20                  @ timeout 5s approx.
    bl delay

100:
    pop {r2-r9,pc}             @ restaur registers
/******************************************************************/
/*    timeout                                                   */
/******************************************************************/
/* r0 contains delay  */

delay:
    push {r1,lr}           @ save  registers
    ldr r1,iCst30000000
    mul r0,r1,r0
1:
    subs r0,r0,#1
    bge 1b
100:
    pop {r1,pc}             @ restaur registers
iCst30000000:       .int 30000000
/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "../affichage.inc"

Create a GUI animation where the string "Hello World! " appears to rotate right by periodically moving the last letter to the front. The direction of rotation reverses when the user clicks on the text.


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

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

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessResult:  .ascii "Counter = "      @ 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 r4,#0
1:    @ begin loop
    mov r0,r4

    ldr r1,iAdrsMessValeur     @ display value
    bl conversion10             @ call function with 2 parameter (r0,r1)
    ldr r0,iAdrszMessResult
    bl affichageMess            @ display message
    add r4,#1                   @ increment counter
    mov r0,r4
    mov r1,#6              @ division conuter by 6
    bl division
    cmp r3,#0              @ remainder = zéro ?
    bne 1b                @ no ->begin loop one

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

iAdrsMessValeur:          .int sMessValeur
iAdrszMessResult:         .int szMessResult
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}      @ save  registres
    mov r2,#0                  @ counter length
1:      @ loop length calculation
    ldrb r1,[r0,r2]           @ read octet start position + index
    cmp r1,#0                  @ if 0 its over
    addne r2,r2,#1            @ else add 1 in the length
    bne 1b                    @ and loop
                                @ so here r2 contains the length of the message
    mov r1,r0        			@ address message in r1
    mov r0,#STDOUT      		@ code to write to the standard output Linux
    mov r7, #WRITE             @ code call system "write"
    svc #0                      @ call systeme
    pop {r0,r1,r2,r7,lr}        @ restaur des  2 registres */
    bx lr                       @ return
/******************************************************************/
/*     Converting a register to a decimal                                 */
/******************************************************************/
/* r0 contains value and r1 address area   */
conversion10:
    push {r1-r4,lr}    @ save registers
    mov r3,r1
    mov r2,#10

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

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

The code initializes a value to 0, then enters a do-while loop where it increments the value by 1 and prints it, continuing as long as the value modulo 6 is not 0. The loop is guaranteed to execute at least once.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program stringLength.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
sMessResultByte:        .asciz "===Byte Length=== : @ \n"
sMessResultChar:        .asciz "===Character Length=== : @ \n"
szString1:          .asciz "møøse€"
szCarriageReturn:   .asciz "\n"

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:        .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                 @ entry of program
    ldr r0,iAdrszString1
    bl affichageMess                  @ display string
    ldr r0,iAdrszCarriageReturn
    bl affichageMess

    ldr r0,iAdrszString1
    mov r1,#0
1:                                    @ loop compute length bytes
    ldrb r2,[r0,r1]
    cmp r2,#0
    addne r1,#1
    bne 1b

    mov r0,r1                         @ result display
    ldr r1,iAdrsZoneConv
    bl conversion10                   @ call decimal conversion
    ldr r0,iAdrsMessResultByte
    ldr r1,iAdrsZoneConv              @ insert conversion in message
    bl strInsertAtCharInc
    bl affichageMess

    ldr r0,iAdrszString1
    mov r1,#0
    mov r3,#0
2:                                    @ loop compute length characters
    ldrb r2,[r0,r1]
    cmp r2,#0
    beq 6f
    and r2,#0b11100000                @ 3 bytes ?
    cmp r2,#0b11100000
    bne 3f
    add r3,#1
    add r1,#3
    b 2b
3:
    and r2,#0b11000000                @ 2 bytes ?
    cmp r2,#0b11000000
    bne 4f
    add r3,#1
    add r1,#2
    b 2b
4:                                    @ else 1 byte
    add r3,#1
    add r1,#1
    b 2b

6:
    mov r0,r3
    ldr r1,iAdrsZoneConv
    bl conversion10                   @ call decimal conversion
    ldr r0,iAdrsMessResultChar
    ldr r1,iAdrsZoneConv              @ insert conversion in message
    bl strInsertAtCharInc
    bl affichageMess
100:                                  @ standard end of the program
    mov r0, #0                        @ return code
    mov r7, #EXIT                     @ request to exit program
    svc #0                            @ perform the system call

iAdrszCarriageReturn:     .int szCarriageReturn
iAdrsMessResultByte:      .int sMessResultByte
iAdrsMessResultChar:      .int sMessResultChar
iAdrszString1:            .int szString1
iAdrsZoneConv:            .int sZoneConv
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
møøse€
===Byte Length=== : 10
===Character Length=== : 6

calculate the character and byte length of a string, considering UTF-8 and UTF-16 encodings. They handle non-BMP code points correctly, providing actual character counts in code points, not in code unit counts. The codes also have the ability to provide the string length in graphemes if the language supports it.


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

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

.equ O_RDONLY, 0                         @ open for reading only

.equ BUFFERSIZE,          4              @ random number 32 bits

/* Initialized data */
.data
szFileName:              .asciz "/dev/urandom"      @ see linux doc
szCarriageReturn:        .asciz "\n"
/* datas error display */
szMessErreur:        .asciz "Error detected.\n"
szMessErr:           .ascii "Error code hexa : "
sHexa:               .space 9,' '
                     .ascii "  decimal :  "
sDeci:               .space 15,' '
                     .asciz "\n"
/* datas message display */
szMessResult:        .ascii "Random number :"
sValue:              .space 12,' '
                     .asciz "\n"
/* UnInitialized data */
.bss
sBuffer:             .skip BUFFERSIZE             @ buffer result

/*  code section */
.text
.global main
main:
    ldr r0,iAdrszFileName               @ File name
    mov r1,#O_RDONLY                    @  flags
    mov r2,#0                           @ mode
    mov r7,#OPEN                        @ open file
    svc #0
    cmp r0,#0                           @ error ?
    ble error
    mov r8,r0                           @ save FD
    mov r4,#0                           @ loop counter
1:
    mov r0,r8                           @ File Descriptor
    ldr r1,iAdrsBuffer                  @ buffer address
    mov r2,#BUFFERSIZE                  @ buffer size
    mov r7,#READ                        @ call system read file
    svc 0
    cmp r0,#0                           @ read error ?
    ble error
    ldr r1,iAdrsBuffer                  @ buffer address
    ldr r0,[r1]                         @ display buffer value
    ldr r1,iAdrsValue
    bl conversion10
    ldr r0,iAdrszMessResult
    bl affichageMess
    add r4,#1                           @ increment counter
    cmp r4,#10                          @ maxi ?
    blt 1b                              @ no -> loop

end:
    mov r0,r8
    mov r7, #CLOSE                      @ call system close file
    svc #0
    cmp r0,#0
    blt error
    mov r0,#0                           @ return code
    b 100f
error:
    ldr r1,iAdrszMessErreur             @ error message
    bl   displayError
    mov r0,#1                           @ return error code
100:                                    @ standard end of the program
    mov r7, #EXIT                       @ request to exit program
    svc 0                               @ perform system call
iAdrsBuffer:               .int sBuffer
iAdrsValue:                .int sValue
iAdrszMessResult:          .int szMessResult
iAdrszFileName:            .int szFileName
iAdrszMessErreur:          .int szMessErreur
iAdrszCarriageReturn:      .int szCarriageReturn

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

demonstrate how to generate a random 32-bit number using the system's built-in mechanism, not just a software algorithm.


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

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

.align 4
iGraine:  .int 123456
.equ NBELEMENTS,      10
TableNumber:	     .int   1,2,3,4,5,6,7,8,9,10

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                           @ entry of program
    ldr r0,iAdrTableNumber                      @ address number table
    mov r1,#NBELEMENTS                          @ number of élements
    bl knuthShuffle
    ldr r2,iAdrTableNumber
    mov r3,#0
1:                                              @ loop display table
    ldr r0,[r2,r3,lsl #2]
    ldr r1,iAdrsMessValeur                      @ display value
    bl conversion10                             @ call function
    ldr r0,iAdrsMessResult
    bl affichageMess                            @ display message
    add r3,#1
    cmp r3,#NBELEMENTS - 1
    ble 1b

    ldr r0,iAdrszCarriageReturn
    bl affichageMess
    /*    2e shuffle             */
    ldr r0,iAdrTableNumber                     @ address number table
    mov r1,#NBELEMENTS                         @ number of élements
    bl knuthShuffle
    ldr r2,iAdrTableNumber
    mov r3,#0
2:                                             @ loop display table
    ldr r0,[r2,r3,lsl #2]
    ldr r1,iAdrsMessValeur                     @ display value
    bl conversion10                            @ call function
    ldr r0,iAdrsMessResult
    bl affichageMess                           @ display message
    add r3,#1
    cmp r3,#NBELEMENTS - 1
    ble 2b

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

iAdrsMessValeur:          .int sMessValeur
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrsMessResult:          .int sMessResult
iAdrTableNumber:          .int TableNumber

/******************************************************************/
/*     Knuth Shuffle                                             */
/******************************************************************/
/* r0 contains the address of table */
/* r1 contains the number of elements */
knuthShuffle:
    push {r2-r5,lr}                                    @ save registers
    mov r5,r0                                          @ save table address
    mov r2,#0                                          @ start index
1:
    mov r0,r2                                          @ generate aleas
    bl genereraleas
    ldr r3,[r5,r2,lsl #2]                              @ swap number on the table
    ldr r4,[r5,r0,lsl #2]
    str r4,[r5,r2,lsl #2]
    str r3,[r5,r0,lsl #2]
    add r2,#1                                           @ next number
    cmp r2,r1                                           @ end ?
    blt 1b                                              @ no -> loop

100:
    pop {r2-r5,lr}
    bx lr                                               @ return

/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                          @ save  registres
    mov r2,#0                                      @ counter length
1:                                                 @ loop length calculation
    ldrb r1,[r0,r2]                                @ read octet start position + index
    cmp r1,#0                                      @ if 0 its over
    addne r2,r2,#1                                 @ else add 1 in the length
    bne 1b                                         @ and loop
                                                   @ so here r2 contains the length of the message
    mov r1,r0                                      @ address message in r1
    mov r0,#STDOUT                                 @ code to write to the standard output Linux
    mov r7, #WRITE                                 @ code call system "write"
    svc #0                                         @ call systeme
    pop {r0,r1,r2,r7,lr}                           @ restaur des  2 registres */
    bx lr                                          @ return
/******************************************************************/
/*     Converting a register to a decimal unsigned                */
/******************************************************************/
/* r0 contains value and r1 address area   */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes          */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                                @ save registers
    mov r3,r1
    mov r2,#LGZONECAL

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

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

/***************************************************/
/*   division par 10   unsigned                    */
/***************************************************/
/* r0 dividende   */
/* r0 quotient */
/* r1 remainder  */
divisionpar10U:
    push {r2,r3,r4, lr}
    mov r4,r0                                          @ save value
    //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
/***************************************************/
/*   Generation random number                  */
/***************************************************/
/* r0 contains limit  */
genereraleas:
    push {r1-r4,lr}                                    @ save registers
    ldr r4,iAdriGraine
    ldr r2,[r4]
    ldr r3,iNbDep1
    mul r2,r3,r2
    ldr r3,iNbDep1
    add r2,r2,r3
    str r2,[r4]                                        @ maj de la graine pour l appel suivant
    cmp r0,#0
    beq 100f
    mov r1,r0                                          @ divisor
    mov r0,r2                                          @ dividende
    bl division
    mov r0,r3                                          @ résult = remainder

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

implement the Knuth shuffle (also known as the Fisher-Yates shuffle) algorithm. This algorithm randomly shuffles the elements of an array in-place. The shuffling process involves iterating from the last index of the array down to 1, and for each index, swapping the element at that index with an element at a random index within the range of 0 to the current index. If in-place modification of the array is not possible in the used programming language, the algorithm can be adjusted to return a new shuffled array. The algorithm can also be modified to iterate from left to right if needed.


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

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

.equ STRINGSIZE,          500

/* Initialized data */
.data
szMessString:            .asciz "String :\n"
szMessEncrip:            .asciz "\nEncrypted :\n"
szMessDecrip:            .asciz "\nDecrypted :\n"
szString1:               .asciz "Why study medicine because there is internet ?"

szCarriageReturn:       .asciz "\n"

/* UnInitialized data */
.bss
szString2:                .skip  STRINGSIZE
szString3:                .skip  STRINGSIZE
/*  code section */
.text
.global main
main:

    ldr r0,iAdrszMessString                     @ display message
    bl affichageMess
    ldr r0,iAdrszString1                        @ display string
    bl affichageMess
    ldr r0,iAdrszString1
    ldr r1,iAdrszString2
    mov r2,#20                                  @ key
    bl encrypt
    ldr r0,iAdrszMessEncrip
    bl affichageMess
    ldr r0,iAdrszString2                        @ display string
    bl affichageMess
    ldr r0,iAdrszString2
    ldr r1,iAdrszString3
    mov r2,#20                                  @ key
    bl decrypt
    ldr r0,iAdrszMessDecrip
    bl affichageMess
    ldr r0,iAdrszString3                        @ display string
    bl affichageMess
    ldr r0,iAdrszCarriageReturn
    bl affichageMess
100:                                            @ standard end of the program
    mov r0, #0                                  @ return code
    mov r7, #EXIT                               @ request to exit program
    svc 0                                       @ perform system call
iAdrszMessString:         .int szMessString
iAdrszMessDecrip:         .int szMessDecrip
iAdrszMessEncrip:         .int szMessEncrip
iAdrszString1:            .int szString1
iAdrszString2:            .int szString2
iAdrszString3:            .int szString3
iAdrszCarriageReturn:     .int szCarriageReturn
/******************************************************************/
/*     encrypt strings                         */
/******************************************************************/
/* r0 contains the address of the string1 */
/* r1 contains the address of the encrypted string */
/* r2 contains the key (1-25)                     */
encrypt:
    push {r3,r4,lr}           @ save  registers
    mov r3,#0                 @ counter byte string 1
1:
    ldrb r4,[r0,r3]           @ load byte string 1
    cmp r4,#0                 @ zero final ?
    streqb r4,[r1,r3]
    moveq r0,r3
    beq 100f
    cmp r4,#65                @ < A ?
    strltb r4,[r1,r3]
    addlt r3,#1
    blt 1b
    cmp r4,#90                @ > Z
    bgt 2f
    add r4,r2                 @ add key
    cmp r4,#90                @ > Z
    subgt r4,#26
    strb r4,[r1,r3]
    add r3,#1
    b 1b
2:
    cmp r4,#97                @ < a ?
    strltb r4,[r1,r3]
    addlt r3,#1
    blt 1b
    cmp r4,#122               @> z
    strgtb r4,[r1,r3]
    addgt r3,#1
    bgt 1b
    add r4,r2
    cmp r4,#122
    subgt r4,#26
    strb r4,[r1,r3]
    add r3,#1
    b 1b

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

100:
    pop {r3,r4,lr}           @ restaur registers
    bx lr                    @ return
/******************************************************************/
/*     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

implement both encoding and decoding functions of a Caesar cipher. The cipher rotates the alphabet letters based on a key ranging from 1 to 25, replacing each letter with the corresponding next letter in the alphabet. The codes also handle cases of wrapping from Z to A. The codes illustrate that Caesar cipher provides minimal security as it is vulnerable to frequency analysis and brute force attacks. The codes also demonstrate that Caesar cipher is identical to Vigenère cipher with a key length of 1 and to Rot-13 with a key of 13.


EndianTest:
mov r0,#0xFF
mov r1,#0x02000000   ;an arbitrary memory location on the Game Boy Advance.
                     ;(The GBA is always little-endian but this test doesn't use that knowledge to prove it.)
str r0,[r1]          ;on a little-endian CPU a hexdump of 0x02000000 would be: FF 00 00 00
                     ;on a big-endian CPU it would be:                         00 00 00 FF
ldrB r0,[r1]         ;load just the byte at 0x02000000. If the machine is big-endian this will load 00; if little-endian, 0xFF.
cmp r0,#0
beq isBigEndian
;else, do whatever is needed to display "little-endian" to the screen. This part isn't implemented.

determine and print the word size and endianness of the host machine, specifically for an ARM CPU which may be either little-endian or big-endian. The endianness is tested by writing a word to RAM and reading the 0th byte from that memory location.


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

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

.equ NBPOSTESECLAT,          20

/* Initialized data */
.data
szMessFinal:   .asciz "Words are : \n"

szString:            .asciz "Hello,How,Are,You,Today"
szMessError:         .asciz "Error tokenize !!\n"
szCarriageReturn:   .asciz "\n"

/* UnInitialized data */
.bss

/*  code section */
.text
.global main
main:
    ldr r0,iAdrszString                           @ string address
    mov r1,#','                                   @ separator
    bl stTokenize
    cmp r0,#-1                                    @ error ?
    beq 99f
    mov r2,r0                                     @ table address
    ldr r0,iAdrszMessFinal                        @ display message
    bl affichageMess
    ldr r4,[r2]                                   @ number of areas
    add r2,#4                                     @ first area
    mov r3,#0                                     @ loop counter
1:                                                @ display loop
    ldr r0,[r2,r3, lsl #2]                        @ address area
    bl affichageMess
    ldr r0,iAdrszCarriageReturn                   @ display carriage return
    bl affichageMess
    add r3,#1                                     @ counter + 1
    cmp r3,r4                                     @ end ?
    blt 1b                                        @ no -> loop

    b 100f
99:                                               @ display error message
    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
iAdrszString:             .int szString
iAdrszFinalString:       .int szFinalString
iAdrszMessFinal:          .int szMessFinal
iAdrszMessError:          .int szMessError
iAdrszCarriageReturn:    .int szCarriageReturn
/******************************************************************/
/*     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 systeme
    pop {r0,r1,r2,r7,lr}                        @ restaur des  2 registres
    bx lr                                       @ return
/*******************************************************************/
/* Separate string by separator into an array                     */
/* areas are store on the heap Linux                               */
/*******************************************************************/
/* r0 contains string address */
/* r1 contains separator character (, or . or : )    */
/* r0 returns table address with first item = number areas */
/* and other items contains pointer of each string     */
stTokenize:
    push {r1-r8,lr}                                 @ save des registres
    mov r6,r0
    mov r8,r1                                       @ save separator
    bl strLength                                    @ length string for place reservation on the heap
    mov r4,r0
    ldr r5,iTailleTable
    add r5,r0
    and r5,#0xFFFFFFFC
    add r5,#4                                       @ align word on the heap
                                                    @ place reservation on the heap
    mov r0,#0                                       @ heap address
    mov r7, #0x2D                                   @ call system linux 'brk'
    svc #0                                          @ call system
    cmp r0,#-1                                      @ error call system
    beq 100f
    mov r3,r0                                       @ save address  heap begin
    add r0,r5                                       @ reserve r5 byte on the heap
    mov r7, #0x2D                                   @ call system linux 'brk'
    svc #0
    cmp r0,#-1
    beq 100f
                                                    @ string copy on the heap
    mov r0,r6
    mov r1,r3
1:                                                  @ loop copy string
    ldrb r2,[r0],#1                                 @ read one byte and increment pointer one byte
    strb r2,[r1],#1                                 @ store one byte and increment pointer one byte
    cmp r2,#0                                       @ end of string ?
    bne 1b                                          @ no -> loop

    add r4,r3                                        @ r4 contains address table begin
    mov r0,#0
    str r0,[r4]
    str r3,[r4,#4]
    mov r2,#1                                       @ areas counter
2:                                                  @ loop load string character
    ldrb r0,[r3]
    cmp r0,#0
    beq 3f                                          @ end string
    cmp r0,r8                                       @ separator ?
    addne r3,#1                                     @ no -> next location
    bne 2b                                          @ and loop
    mov r0,#0                                       @ store zero final of string
    strb r0,[r3]
    add r3,#1                                       @ next character
    add r2,#1                                       @ areas counter + 1
    str r3,[r4,r2, lsl #2]                          @ store address area in the table at index r2
    b 2b                                            @ and loop

3:
    str r2,[r4]                                     @ returns number areas
    mov r0,r4
100:
    pop {r1-r8,lr}
    bx lr
iTailleTable: .int 4 * NBPOSTESECLAT
/***************************************************/
/*   calcul size string                            */
/***************************************************/
/* r0 string address                 */
/* r0 returns size string            */
strLength:
    push {r1,r2,lr}
    mov r1,#0                                           @ init counter
1:
   ldrb r2,[r0,r1]                                      @ load byte of string index r1
   cmp r2,#0                                            @ end string ?
   addne r1,#1                                          @ no -> +1 counter
   bne 1b                                               @ and loop

100:
    mov r0,r1
    pop {r1,r2,lr}
    bx lr

"Tokenizes a string by commas into an array, and displays the words to the user separated by a period, including a trailing period."


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

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

.equ BUFFERSIZE,          100

/* Initialized data */
.data
szMessNum: .asciz "Enter number : \n"

szMessError:            .asciz "String is not a number !!!\n"
szMessInteger:          .asciz "String is a integer.\n"
szMessFloat:            .asciz "String is a float.\n"
szMessFloatExp:         .asciz "String is a float with exposant.\n"
szCarriageReturn:       .asciz "\n"

/* UnInitialized data */
.bss
sBuffer:              .skip BUFFERSIZE

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

loop:
    ldr r0,iAdrszMessNum
    bl affichageMess
    mov r0,#STDIN                               @ Linux input console
    ldr r1,iAdrsBuffer                          @ buffer address
    mov r2,#BUFFERSIZE                          @ buffer size
    mov r7, #READ                               @ request to read datas
    swi 0                                       @ call system
    ldr r1,iAdrsBuffer                          @ buffer address
    mov r2,#0                                   @ end of string
    sub r0,#1                                   @ replace character 0xA
    strb r2,[r1,r0]                             @ store byte at the end of input string (r0 contains number of characters)
    ldr r0,iAdrsBuffer
    bl controlNumber                            @ call routine
    cmp r0,#0
    bne 1f
    ldr r0,iAdrszMessError                      @ not a number
    bl affichageMess
    b 5f
1:
    cmp r0,#1
    bne 2f
    ldr r0,iAdrszMessInteger                    @ integer
    bl affichageMess
    b 5f
2:
    cmp r0,#2
    bne 3f
    ldr r0,iAdrszMessFloat                      @ float
    bl affichageMess
    b 5f
3:
    cmp r0,#3
    bne 5f
    ldr r0,iAdrszMessFloatExp                   @ float with exposant
    bl affichageMess
5:
    b loop

100:                                            @ standard end of the program
    mov r0, #0                                  @ return code
    mov r7, #EXIT                               @ request to exit program
    svc 0                                       @ perform system call
iAdrszMessNum:            .int szMessNum
iAdrszMessError:          .int szMessError
iAdrszMessInteger:        .int szMessInteger
iAdrszMessFloat:          .int szMessFloat
iAdrszMessFloatExp:       .int szMessFloatExp
iAdrszCarriageReturn:     .int szCarriageReturn
iAdrsBuffer:              .int sBuffer
/******************************************************************/
/*     control if string is number                          */
/******************************************************************/
/* r0 contains the address of the string */
/* r0 return 0 if not a number       */
/* r0 return 1 if integer   eq 12345 or -12345      */
/* r0 return 2 if float     eq 123.45 or 123,45  or -123,45     */
/* r0 return 3 if float with exposant  eq 123.45E30 or -123,45E-30        */
controlNumber:
    push {r1-r4,lr}                       @ save  registers
    mov r1,#0
    mov r3,#0          @ point counter
1:
    ldrb r2,[r0,r1]
    cmp r2,#0
    beq 5f
    cmp r2,#' '
    addeq r1,#1
    beq   1b
    cmp r2,#'-'                    @ negative ?
    addeq r1,#1
    beq 2f
    cmp r2,#'+'                    @ positive ?
    addeq r1,#1
2:
    ldrb r2,[r0,r1]                @ control space
    cmp r2,#0                      @ end ?
    beq 5f
    cmp r2,#' '
    addeq r1,#1
    beq 2b
3:
    ldrb r2,[r0,r1]
    cmp r2,#0                 @ end ?
    beq 10f
    cmp r2,#'E'               @ exposant ?
    beq 6f
    cmp r2,#'e'               @ exposant ?
    beq 6f
    cmp r2,#'.'               @ point ?
    addeq r3,#1               @ yes increment counter
    addeq r1,#1
    beq 3b
    cmp r2,#','               @ comma ?
    addeq r3,#1               @ yes increment counter
    addeq r1,#1
    beq 3b
    cmp r2,#'0'               @ control digit < 0
    blt 5f
    cmp r2,#'9'               @ control digit > 0
    bgt 5f
    add r1,#1                 @ no error loop digit
    b 3b
5:                            @ error detected
    mov r0,#0
    b 100f
6:    @ float with exposant
    add r1,#1
    ldrb r2,[r0,r1]
    cmp r2,#0             @ end ?
    moveq r0,#0           @ error
    beq 100f
    cmp r2,#'-'           @ negative exposant ?
    addeq r1,#1
    mov r4,#0             @ nombre de chiffres
7:
    ldrb r2,[r0,r1]
    cmp r2,#0             @ end ?
    beq 9f
    cmp r2,#'0'           @ control digit < 0
    blt 8f
    cmp r2,#'9'           @ control digit > 0
    bgt 8f
    add r1,#1
    add r4,#1             @ counter digit
    b 7b
8:
    mov r0,#0
    b 100f
9:
    cmp r4,#0             @ number digit exposant = 0 -> error
    moveq r0,#0           @ erreur
    beq 100f
    cmp r4,#2             @ number digit exposant > 2 -> error
    movgt r0,#0           @ error
    bgt 100f
    mov r0,#3             @ valid float with exposant
    b 100f
10:
    cmp r3,#0
    moveq r0,#1           @ valid integer
    beq 100f
    cmp r3,#1             @ number of point or comma = 1 ?
    moveq r0,#2           @ valid float
    movgt r0,#0           @ error
100:
    pop {r1-r4,lr}                         @ restaur des  2 registres
    bx lr                                        @ return
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                       @ save  registers
    mov r2,#0                                   @ counter length */
1:                                              @ loop length calculation
    ldrb r1,[r0,r2]                             @ read octet start position + index
    cmp r1,#0                                   @ if 0 its over
    addne r2,r2,#1                              @ else add 1 in the length
    bne 1b                                      @ and loop
                                                @ so here r2 contains the length of the message
    mov r1,r0                                   @ address message in r1
    mov r0,#STDOUT                              @ code to write to the standard output Linux
    mov r7, #WRITE                              @ code call system "write"
    svc #0                                      @ call system
    pop {r0,r1,r2,r7,lr}                        @ restaur registers
    bx lr                                       @ return

"Output: Function to check if a given string can be interpreted as a numeric value, including floating point and negative numbers, in the language's syntax."


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

/* Constantes    */
.equ BUFFERSIZE,   100
.equ STDIN,  0     @ Linux input console
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ READ,   3     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
/* Initialized data */
.data
szMessNum:           .asciz "Enter number : \n"
szCarriageReturn:  .asciz "\n"
szMessResult:       .ascii "Increment number is = "      @ message result
sMessValeur:        .fill 12, 1, ' '
                       .asciz "\n"

/* UnInitialized data */
.bss
sBuffer:    .skip    BUFFERSIZE

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

    ldr r0,iAdrszMessNum
    bl affichageMess
    mov r0,#STDIN         @ Linux input console
    ldr r1,iAdrsBuffer   @ buffer address
    mov r2,#BUFFERSIZE   @ buffer size
    mov r7, #READ         @ request to read datas
    swi 0                  @ call system
    ldr r1,iAdrsBuffer    @ buffer address
    mov r2,#0                @ end of string
    strb r2,[r1,r0]         @ store byte at the end of input string (r0
    @
    ldr r0,iAdrsBuffer    @ buffer address
    bl conversionAtoD    @ conversion string in number in r0
    @ increment r0
    add r0,#1
    @ conversion register to string
    ldr r1,iAdrsMessValeur
    bl conversion10S       @ call conversion
    ldr r0,iAdrszMessResult
    bl affichageMess            @ display message

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

iAdrsMessValeur:        .int sMessValeur
iAdrszMessNum:           .int szMessNum
iAdrsBuffer:             .int sBuffer
iAdrszMessResult:       .int szMessResult
iAdrszCarriageReturn:  .int szCarriageReturn
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {fp,lr}    			/* save  registres */
    push {r0,r1,r2,r7}    		/* save others registers */
    mov r2,#0   				/* counter length */
1:      /* loop length calculation */
    ldrb r1,[r0,r2]  			/* read octet start position + index */
    cmp r1,#0       			/* if 0 its over */
    addne r2,r2,#1   			/* else add 1 in the length */
    bne 1b          			/* and loop */
                                /* so here r2 contains the length of the message */
    mov r1,r0        			/* address message in r1 */
    mov r0,#STDOUT      		/* code to write to the standard output Linux */
    mov r7, #WRITE             /* code call system "write" */
    swi #0                      /* call systeme */
    pop {r0,r1,r2,r7}     		/* restaur others registers */
    pop {fp,lr}    				/* restaur des  2 registres */
    bx lr	        			/* return  */

 /******************************************************************/
/*     Convert a string to a number stored in a registry          */
/******************************************************************/
/* r0 contains the address of the area terminated by 0 or 0A */
/* r0 returns a number                           */
conversionAtoD:
    push {fp,lr}         @ save 2 registers
    push {r1-r7}         @ save others registers
    mov r1,#0
    mov r2,#10           @ factor
    mov r3,#0            @ counter
    mov r4,r0            @ save address string -> r4
    mov r6,#0            @ positive sign by default
    mov r0,#0            @ initialization to 0
1:     /* early space elimination loop */
    ldrb r5,[r4,r3]     @ loading in r5 of the byte located at the beginning + the position
    cmp r5,#0            @ end of string -> end routine
    beq 100f
    cmp r5,#0x0A        @ end of string -> end routine
    beq 100f
    cmp r5,#' '          @ space ?
    addeq r3,r3,#1      @ yes we loop by moving one byte
    beq 1b
    cmp r5,#'-'          @ first character is -
    moveq r6,#1         @  1 -> r6
    beq 3f              @ then move on to the next position
2:   /* beginning of digit processing loop */
    cmp r5,#'0'          @ character is not a number
    blt 3f
    cmp r5,#'9'          @ character is not a number
    bgt 3f
    /* character is a number */
    sub r5,#48
    umull r0,r1,r2,r0         @ multiply par factor 10
	cmp r1,#0           @ overflow ?
    bgt 99f            @ overflow error
    add r0,r5            @ add to  r0
3:
    add r3,r3,#1         @ advance to the next position
    ldrb r5,[r4,r3]     @ load byte
    cmp r5,#0            @ end of string -> end routine
    beq 4f
    cmp r5,#0x0A            @ end of string -> end routine
    beq 4f
    b 2b                 @ loop
4:
    cmp r6,#1            @ test r6 for sign
    moveq r1,#-1
    muleq r0,r1,r0       @ if negatif, multiply par -1
    b 100f
99:  /* overflow error */
    ldr r0,=szMessErrDep
    bl   affichageMess
    mov r0,#0      @ return  zero  if error
100:
    pop {r1-r7}          @ restaur other registers
    pop {fp,lr}          @ restaur   2 registers
    bx lr                 @return procedure
/* constante program */
szMessErrDep:  .asciz  "Too large: overflow 32 bits.\n"
.align 4

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