Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program loopdownward.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,#10
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
    subs r4,#1                   @ decrement counter
    bge 1b                      @ loop if greather

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

The code performs a countdown from 10 to 0 using a downward for loop.


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

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
.equ MAXI,   20
/*********************************/
/* 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,#2                   @ increment counter by 2
    cmp r4,#MAXI              @
    ble 1b                @ loop

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

demonstrate a for-loop with a step-value greater than one.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program jensen.s   */
/* compil as with option  -mcpu=<processor> -mfpu=vfpv4 -mfloat-abi=hard  */
/* link with gcc          */

/* Constantes    */
.equ EXIT,   1                           @ Linux syscall
/* Initialized data */
.data

szFormat: .asciz "Result = %.8f \n"
.align 4

/* UnInitialized data */
.bss

/*  code section */
.text
.global main
main:
    mov r0,#1                                   @ first indice
    mov r1,#100                                 @ last indice
    adr r2,funcdiv                              @ address function
    bl funcSum
    vcvt.f64.f32  d1, s0                        @ conversion double float for print by C
    ldr r0,iAdrszFormat                         @ display format
    vmov r2,r3,d1                               @ parameter function printf for float double
    bl printf                                   @ display float double

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

iAdrszFormat:             .int szFormat
/******************************************************************/
/*     function sum                                               */
/******************************************************************/
/* r0 contains begin  */
/* r1 contains end */
/* r2 contains address function */

/* r0 return result                      */
funcSum:
    push {r0,r3,lr}                       @ save  registers
    mov r3,r0
    mov r0,#0                             @ init r0
    vmov s3,r0                            @ and s3
    vcvt.f32.s32 s3, s3                   @ convert in float single précision (32bits)
1:                                        @ begin loop
    mov r0,r3                             @ loop indice -> parameter function
    blx r2                                @ call function address in r2
    vadd.f32 s3,s0                        @ addition float
    add r3,#1                             @ increment indice
    cmp r3,r1                             @ end ?
    ble 1b                                @ no loop
    vmov s0,s3                            @ return float result in s0

100:
    pop {r0,r3,lr}                        @ restaur registers
    bx lr                                 @ return
/******************************************************************/
/*     compute 1/r0                                               */
/******************************************************************/
/* r0 contains the value                 */
/* r0 return result                      */
funcdiv:
    push {r1,lr}                       @ save  registers
    vpush {s1}                         @ save float registers
    cmp r0,#0                          @ division by zero -> end
    beq 100f
    ldr r1,fUn                         @ load float constant 1.0
    vmov s0,r1                         @ in float register s3
    vmov s1,r0                         @
    vcvt.f32.s32 s1, s1                @conversion in float single précision (32 bits)
    vdiv.f32 s0,s0,s1                  @ division 1/r0
                                       @ and return result in s0
100:
    vpop {s1}                          @ restaur float registers
    pop {r1,lr}                        @ restaur registers
    bx lr                              @ return
fUn:                .float 1

implement Jensen's Device, a programming technique devised by Jørn Jensen. The technique is an exercise in call by name, where it computes the 100th harmonic number. The program uses a sum procedure that takes in four parameters, with the first and the last parameter being passed by name. This allows the expression passed as an actual parameter to be re-evaluated in the caller's context every time the corresponding formal parameter's value is required. The program also demonstrates the importance of passing the first parameter by name or by reference, as changes to it within the sum procedure need to be visible in the caller's context when computing each of the values to be added.


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

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

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessResult1:      .asciz "List1 < List2 \n"           @ message result
szMessResult2:      .asciz "List1 => List2 \n"           @ message result
szCarriageReturn:  .asciz "\n"

iTabList1:         .int  1,2,3,4,5
.equ NBELEMENTS1,   (. - iTabList1) /4
iTabList2:         .int  1,2,1,5,2,2
.equ NBELEMENTS2,   (. - iTabList2) /4
iTabList3:         .int  1,2,3,4,5
.equ NBELEMENTS3,   (. - iTabList3) /4
iTabList4:         .int  1,2,3,4,5,6
.equ NBELEMENTS4,   (. - iTabList4) /4
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                       @ entry of program
    ldr r0,iAdriTabList1
    mov r1,#NBELEMENTS1
    ldr r2,iAdriTabList2
    mov r3,#NBELEMENTS2
    bl listeOrder
    cmp r0,#0                               @ false ?
    beq 1f                                  @ yes
    ldr r0,iAdrszMessResult1                @ list 1 < list 2
    bl affichageMess                        @ display message
    b 2f
1:
    ldr r0,iAdrszMessResult2
    bl affichageMess                        @ display message

2:
    ldr r0,iAdriTabList1
    mov r1,#NBELEMENTS1
    ldr r2,iAdriTabList3
    mov r3,#NBELEMENTS3
    bl listeOrder
    cmp r0,#0                               @ false ?
    beq 3f                                  @ yes
    ldr r0,iAdrszMessResult1                @ list 1 < list 2
    bl affichageMess                        @ display message
    b 4f
3:
    ldr r0,iAdrszMessResult2
    bl affichageMess                        @ display message
4:
    ldr r0,iAdriTabList1
    mov r1,#NBELEMENTS1
    ldr r2,iAdriTabList4
    mov r3,#NBELEMENTS4
    bl listeOrder
    cmp r0,#0                               @ false ?
    beq 5f                                  @ yes
    ldr r0,iAdrszMessResult1                @ list 1 < list 2
    bl affichageMess                        @ display message
    b 6f
5:
    ldr r0,iAdrszMessResult2
    bl affichageMess                        @ display message
6:
100:                                        @ standard end of the program
    mov r0, #0                              @ return code
    mov r7, #EXIT                           @ request to exit program
    svc #0                                  @ perform the system call
iAdriTabList1:             .int iTabList1
iAdriTabList2:             .int iTabList2
iAdriTabList3:             .int iTabList3
iAdriTabList4:             .int iTabList4
iAdrszMessResult1:        .int szMessResult1
iAdrszMessResult2:        .int szMessResult2
iAdrszCarriageReturn:     .int szCarriageReturn
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of list 1 */
/* r1 contains list 1 size           */
/* r2 contains the address of list 2 */
/* r3 contains list 2 size           */
/* r0 returns 1 if list1 < list2     */
/* r0 returns 0 else                 */
listeOrder:
    push {r1-r7,lr}                   @ save  registres
    cmp r1,#0                         @ list 1 size = zero ?
    moveq r0,#-1                      @ yes -> error
    beq 100f
    cmp r3,#0                         @ list 2 size = zero ?
    moveq r0,#-2                      @ yes -> error
    beq 100f
    mov r4,#0                         @ index list 1
    mov r5,#0                         @ index list 2
1:
    ldr r6,[r0,r4,lsl #2]             @ load list 1 element
    ldr r7,[r2,r5,lsl #2]             @ load list 2 element
    cmp r6,r7                         @ compar
    movgt r0,#0                       @ list 1 > list 2 ?
    bgt 100f
    beq 2f                            @ list 1 = list 2
    add r4,#1                         @ increment index 1
    cmp r4,r1                         @ end list ?
    movge r0,#1                       @ yes -> ok list 1 < list 2
    bge 100f
    b 1b                              @ else loop
2:
    add r4,#1                         @ increment index 1
    cmp r4,r1                         @ end list ?
    bge 3f                            @ yes -> verif size
    add r5,#1                         @ else increment index 2
    cmp r5,r3                         @ end list 2 ?
    movge r0,#0                       @ yes -> list 2 < list 1
    bge 100f
    b 1b                              @ else loop
3:
   cmp r1,r3                          @ compar size
   movge r0,#0                        @ list 2 < list 1
   movlt r0,#1                        @ list 1 < list 2
100:
    pop {r1-r7,lr}                    @ restaur registers
    bx lr                             @ return
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                   @ save  registres
    mov r2,#0                               @ counter length
1:                                          @ loop length calculation
    ldrb r1,[r0,r2]                         @ read octet start position + index
    cmp r1,#0                               @ if 0 its over
    addne r2,r2,#1                          @ else add 1 in the length
    bne 1b                                  @ and loop
                                            @ so here r2 contains the length of the message
    mov r1,r0                               @ address message in r1
    mov r0,#STDOUT                          @ code to write to the standard output Linux
    mov r7, #WRITE                          @ code call system "write"
    svc #0                                  @ call systeme
    pop {r0,r1,r2,r7,lr}                    @ restaur registers */
    bx lr                                   @ return

"Function to compare and order two numerical lists lexicographically, returning true if the first list should be ordered before the second, and false otherwise."


Works with: as version Raspberry Pi  or android 32 bits with application Termux
/* ARM assembly Raspberry PI  or android 32 bits */
/*  program ackermann.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 MMAXI,   4
.equ NMAXI,   10

/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessResult:        .asciz "Result for @  @  : @ \n"
szMessError:        .asciz "Overflow !!.\n"
szCarriageReturn:   .asciz "\n"

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
sZoneConv:        .skip 24
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                           @ entry of program
    mov r3,#0
    mov r4,#0
1:
    mov r0,r3
    mov r1,r4
    bl ackermann
    mov r5,r0
    mov r0,r3
    ldr r1,iAdrsZoneConv        @ else display odd message
    bl conversion10             @ call decimal conversion
    ldr r0,iAdrsMessResult
    ldr r1,iAdrsZoneConv        @ insert value conversion in message
    bl strInsertAtCharInc
    mov r6,r0
    mov r0,r4
    ldr r1,iAdrsZoneConv        @ else display odd message
    bl conversion10             @ call decimal conversion
    mov r0,r6
    ldr r1,iAdrsZoneConv        @ insert value conversion in message
    bl strInsertAtCharInc
    mov r6,r0
    mov r0,r5
    ldr r1,iAdrsZoneConv        @ else display odd message
    bl conversion10             @ call decimal conversion
    mov r0,r6
    ldr r1,iAdrsZoneConv        @ insert value conversion in message
    bl strInsertAtCharInc
    bl affichageMess
    add r4,#1
    cmp r4,#NMAXI
    blt 1b
    mov r4,#0
    add r3,#1
    cmp r3,#MMAXI
    blt 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
iAdrsMessResult:          .int sMessResult
iAdrsZoneConv:            .int sZoneConv
/***************************************************/
/*     fonction ackermann              */
/***************************************************/
// r0 contains a number m
// r1 contains a number n
// r0 return résult
ackermann:
    push {r1-r2,lr}             @ save  registers
    cmp r0,#0
    beq 5f
    movlt r0,#-1               @ error
    blt 100f
    cmp r1,#0
    movlt r0,#-1               @ error
    blt 100f
    bgt 1f
    sub r0,r0,#1
    mov r1,#1
    bl ackermann
    b 100f
1:
    mov r2,r0
    sub r1,r1,#1
    bl ackermann
    mov r1,r0
    sub r0,r2,#1
    bl ackermann
    b 100f
5:
    adds r0,r1,#1
    bcc 100f
    ldr r0,iAdrszMessError
    bl affichageMess
    bkpt
100:
    pop {r1-r2,lr}             @ restaur registers
    bx lr                      @ return
iAdrszMessError:        .int szMessError
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"

Implement the Ackermann function which is a recursive function that takes two non-negative arguments and returns a value based on the specified conditions. The function should ideally support arbitrary precision due to its rapid growth.


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

/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
.equ NBMAXITEMS,  20   @
/* Initialized data */
.data
szMessLenArea: .ascii "The length of area 3  is : "
sZoneconv:		 .fill 12,1,' '
szCarriageReturn:  .asciz "\n"

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

/* pointer items area 1*/
tablesPoi1:
pt1_1:		.int szString1
pt1_2:   .int szString2
ptVoid_1:		.int 0

/* pointer items area 2*/
tablesPoi2:
pt2_1:		.int szString3
pt2_2:   	.int szString4
pt2_3:   	.int szString5
ptVoid_2:		.int 0

/* UnInitialized data */
.bss
tablesPoi3:    .skip   4 * NBMAXITEMS

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

    @ copy area 1 ->  area 3
    ldr r1,iAdrtablesPoi1  @ begin pointer area 1
    ldr r3,iAdrtablesPoi3  @ begin pointer area 3
    mov r0,#0    @ counter
1:
    ldr r2,[r1,r0,lsl #2]    @ read string pointer address item r0 (4 bytes by pointer)
    cmp r2,#0                @ is null ?
    strne r2,[r3,r0,lsl #2]    @ no store pointer in area 3
    addne r0,#1             @ increment counter
    bne 1b                  @ and loop
    @ copy area 2 ->  area 3
    ldr r1,iAdrtablesPoi2  @ begin pointer area 2
    ldr r3,iAdrtablesPoi3  @ begin pointer area 3
    mov r4,#0    @ counter area 2
2:        @ r0 contains the first void item in area 3
    ldr r2,[r1,r4,lsl #2]    @ read string pointer address item r0 (4 bytes by pointer)
    cmp r2,#0                @ is null ?
    strne r2,[r3,r0,lsl #2]    @ no store pointer in area 3
    addne r0,#1             @ increment counter
    addne r4,#1             @ increment counter
    bne 2b                  @ and loop

	@ count items number in area 3
    ldr r1,iAdrtablesPoi3  @ begin pointer table
    mov r0,#0    @ counter
3:              @ begin loop
    ldr r2,[r1,r0,lsl #2]    @ read string pointer address item r0 (4 bytes by pointer)
    cmp r2,#0                @ is null ?
    addne r0,#1             @ no increment counter
    bne 3b                  @ and loop

    ldr r1,iAdrsZoneconv   @ conversion decimal
    bl conversion10S
    ldr r0,iAdrszMessLenArea
    bl affichageMess

100:   /* standard end of the program */
    mov r0, #0                  @ return code
    pop {fp,lr}                 @restaur 2 registers
    mov r7, #EXIT              @ request to exit program
    swi 0                       @ perform the system call
iAdrtablesPoi1:		.int tablesPoi1
iAdrtablesPoi2:		.int tablesPoi2
iAdrtablesPoi3:		.int tablesPoi3
iAdrszMessLenArea:  .int szMessLenArea
iAdrsZoneconv:		.int  sZoneconv
iAdrszCarriageReturn:  .int  szCarriageReturn
/******************************************************************/
/*     display text with size calculation                         */
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {fp,lr}    			/* save  registres */
    push {r0,r1,r2,r7}    		/* save others registers */
    mov r2,#0   				/* counter length */
1:      	/* loop length calculation */
    ldrb r1,[r0,r2]  			/* read octet start position + index */
    cmp r1,#0       			/* if 0 its over */
    addne r2,r2,#1   			/* else add 1 in the length */
    bne 1b          			/* and loop */
                                /* so here r2 contains the length of the message */
    mov r1,r0        			/* address message in r1 */
    mov r0,#STDOUT      		/* code to write to the standard output Linux */
    mov r7, #WRITE             /* code call system "write" */
    swi #0                      /* call systeme */
    pop {r0,r1,r2,r7}     		/* restaur others registers */
    pop {fp,lr}    				/* restaur des  2 registres */
    bx lr	        			/* return  */

/***************************************************/
/*   conversion register signed décimal     */
/***************************************************/
/* r0 contient le registre   */
/* r1 contient l adresse de la zone de conversion */
conversion10S:
    push {r0-r5,lr}    /* save des registres */
    mov r2,r1       /* debut zone stockage */
    mov r5,#'+'     /* par defaut le signe est + */
    cmp r0,#0       /* nombre négatif ? */
    movlt r5,#'-'     /* oui le signe est - */
    mvnlt r0,r0       /* et inversion en valeur positive */
    addlt r0,#1
    mov r4,#10   /* longueur de la zone */
1: /* debut de boucle de conversion */
    bl divisionpar10 /* division  */
    add r1,#48        /* ajout de 48 au reste pour conversion ascii */
    strb r1,[r2,r4]  /* stockage du byte en début de zone r5 + la position r4 */
    sub r4,r4,#1      /* position précedente */
    cmp r0,#0
    bne 1b	       /* boucle si quotient different de zéro */
    strb r5,[r2,r4]  /* stockage du signe à la position courante */
    subs r4,r4,#1   /* position précedente */
    blt  100f         /* si r4 < 0  fin  */
    /* sinon il faut completer le debut de la zone avec des blancs */
    mov r3,#' '   /* caractere espace */
2:
    strb r3,[r2,r4]  /* stockage du byte  */
    subs r4,r4,#1   /* position précedente */
    bge 2b        /* boucle si r4 plus grand ou egal a zero */
100:  /* fin standard de la fonction  */
    pop {r0-r5,lr}   /*restaur desregistres */
    bx lr

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

demonstrate how to concatenate two arrays.


Works with: as version Raspberry Pi
/* ARM assembly Raspberry PI  */
/*  program problemABC.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 TRUE, 1
.equ FALSE, 0

/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessTitre1:        .asciz "Can_make_word: @ \n"
szMessTrue:          .asciz "True.\n"
szMessFalse:         .asciz "False.\n"
szCarriageReturn:    .asciz "\n"

szTablBloc:          .asciz "BO"
                     .asciz "XK"
                     .asciz "DQ"
                     .asciz "CP"
                     .asciz "NA"
                     .asciz "GT"
                     .asciz "RE"
                     .asciz "TG"
                     .asciz "QD"
                     .asciz "FS"
                     .asciz "JW"
                     .asciz "HU"
                     .asciz "VI"
                     .asciz "AN"
                     .asciz "OB"
                     .asciz "ER"
                     .asciz "FS"
                     .asciz "LY"
                     .asciz "PC"
                     .asciz "ZM"
                     .equ NBBLOC, (. -  szTablBloc) / 3

szWord1:             .asciz "A"
szWord2:             .asciz "BARK"
szWord3:             .asciz "BOOK"
szWord4:             .asciz "TREAT"
szWord5:             .asciz "COMMON"
szWord6:             .asciz "SQUAD"
szWord7:             .asciz "CONFUSE"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
itabTopBloc:         .skip 4 * NBBLOC
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                @ entry of program
    ldr r0,iAdrszWord1
    bl traitBlock                    @ control word

    ldr r0,iAdrszWord2
    bl traitBlock                    @ control word

    ldr r0,iAdrszWord3
    bl traitBlock                    @ control word

    ldr r0,iAdrszWord4
    bl traitBlock                    @ control word

    ldr r0,iAdrszWord5
    bl traitBlock                    @ control word

    ldr r0,iAdrszWord6
    bl traitBlock                    @ control word

    ldr r0,iAdrszWord7
    bl traitBlock                    @ control word

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
iAdrszWord1:              .int szWord1
iAdrszWord2:              .int szWord2
iAdrszWord3:              .int szWord3
iAdrszWord4:              .int szWord4
iAdrszWord5:              .int szWord5
iAdrszWord6:              .int szWord6
iAdrszWord7:              .int szWord7
/******************************************************************/
/*          traitement                                           */
/******************************************************************/
/* r0 contains word */
traitBlock:
    push {r1,lr}        @ save registers
    mov r1,r0
    ldr r0,iAdrszMessTitre1   @ insertion word in message
    bl strInsertAtCharInc
    bl affichageMess          @ display title message
    mov r0,r1
    bl controlBlock           @ control
    cmp r0,#TRUE              @ ok ?
    bne 1f
    ldr r0,iAdrszMessTrue     @ yes
    bl affichageMess
    b 100f
1:                            @ no
    ldr r0,iAdrszMessFalse
    bl affichageMess
100:
    pop {r1,lr}
    bx lr                     @ return
iAdrszMessTitre1:         .int szMessTitre1
iAdrszMessFalse:          .int szMessFalse
iAdrszMessTrue:           .int szMessTrue
/******************************************************************/
/*        control if letters are in block                       */
/******************************************************************/
/* r0 contains word */
controlBlock:
    push {r1-r9,lr}        @ save registers
    mov r5,r0              @ save word address
    ldr r4,iAdritabTopBloc
    ldr r6,iAdrszTablBloc
    mov r2,#0
    mov r3,#0
1:                          @ init table top block used
    str r3,[r4,r2,lsl #2]
    add r2,r2,#1
    cmp r2,#NBBLOC
    blt 1b
    mov r2,#0
2:                          @ loop to load letters
    ldrb r3,[r5,r2]
    cmp r3,#0
    beq 10f                 @ end
    and r3,r3,#0xDF         @ transform in capital letter
    mov r8,#0
3:                          @ begin loop control block
    ldr r7,[r4,r8,lsl #2]   @ block already used ?
    cmp r7,#0
    bne 5f                  @ yes
    add r9,r8,r8,lsl #1     @ no -> index * 3
    ldrb r7,[r6,r9]         @ first block letter
    cmp r3,r7               @ equal ?
    beq 4f
    add r9,r9,#1
    ldrb r7,[r6,r9]         @ second block letter
    cmp r3,r7               @ equal ?
    beq 4f
    b 5f
4:
    mov r7,#1               @ top block
    str r7,[r4,r8,lsl #2]   @ block used
    add r2,r2,#1
    b 2b                    @ next letter
5:
    add r8,r8,#1
    cmp r8,#NBBLOC
    blt 3b
    mov r0,#FALSE           @ no letter find on block -> false
    b 100f
10:                         @ all letters are ok
    mov r0,#TRUE
100:
    pop {r1-r9,lr}
    bx lr                   @ return
iAdritabTopBloc:   .int itabTopBloc
iAdrszTablBloc:    .int szTablBloc
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
Can_make_word: A
True.
Can_make_word: BARK
True.
Can_make_word: BOOK
False.
Can_make_word: TREAT
True.
Can_make_word: COMMON
False.
Can_make_word: SQUAD
True.
Can_make_word: CONFUSE
True.

"Output: The code defines a function that checks if a given word can be spelled using a specific collection of ABC blocks. Each block contains two letters and can only be used once. The function is case-insensitive and returns a boolean value based on whether or not the word can be formed."


Works with: as version Raspberry Pi  or android 32 bits with application Termux
/* ARM assembly Raspberry PI  */
/*  program MD5.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 LGHASH, 16                  // result length
.equ ZWORKSIZE,        1000      // work area size

/*******************************************/
/* Structures                               */
/********************************************/
/* example structure  variables  */
    .struct  0
var_a:                     // a
    .struct  var_a + 4
var_b:                     // b
    .struct  var_b + 4
var_c:                     // c
    .struct  var_c + 4
var_d:                     // d
    .struct  var_d + 4
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessTest1:           .asciz "abc"
szMessTest4:           .asciz "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
szMessTest2:           .asciz "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
szMessTest3:           .asciz "abcdefghijklmnopqrstuvwxyz"
szMessFinPgm:          .asciz "Program End ok.\n"
szMessResult:          .asciz "Result for "
szMessResult1:         .asciz " => "
szMessSizeError:       .asciz "\033[31mWork area too small !! \033[0m \n"
szCarriageReturn:   .asciz "\n"

.align 4
/* array constantes K */
tbConstK:  .int 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee
           .int 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501
           .int 0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be
           .int 0x6b901122,0xfd987193,0xa679438e,0x49b40821
           .int 0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa
           .int 0xd62f105d,0x2441453,0xd8a1e681,0xe7d3fbc8
           .int 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed
           .int 0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a
           .int 0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c
           .int 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70
           .int 0x289b7ec6,0xeaa127fa,0xd4ef3085,0x4881d05
           .int 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665
           .int 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039
           .int 0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1
           .int 0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1
           .int 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391

/* array rotation coef R */
tbRotaR:   .int  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22
           .int  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20
           .int  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23
           .int  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21

tbConstH:            .int 0x67452301       // H0
                     .int 0xEFCDAB89       // H1
                     .int 0x98BADCFE       // H2
                     .int 0x10325476       // H3

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
.align 4
sZoneConv:                   .skip 24
tbH:                         .skip 4 * 4         @ 4 variables H
tbabcd:                      .skip 4 * 4         @ 4 variables a b c d
sZoneTrav:                   .skip 1000
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                           @ entry of program

    ldr r0,iAdrszMessTest1
    bl computeExemple

    ldr r0,iAdrszMessTest2
    bl computeExemple

    ldr r0,iAdrszMessTest3
    bl computeExemple

    ldr r0,iAdrszMessTest4
    bl computeExemple

    ldr r0,iAdrszMessFinPgm
    bl affichageMess            @ 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
iAdrszMessResult:         .int szMessResult
iAdrszMessResult1:        .int szMessResult1
iAdrszMessTest1:          .int szMessTest1
iAdrszMessTest2:          .int szMessTest2
iAdrszMessTest3:          .int szMessTest3
iAdrszMessTest4:          .int szMessTest4
iAdrsZoneTrav:            .int sZoneTrav
iAdrsZoneConv:            .int sZoneConv
iAdrszMessFinPgm:         .int szMessFinPgm
iAdrszMessSizeError:      .int szMessSizeError
/***********************************************/
/*     compute exemple                         */
/***********************************************/
/* r0 contains the address of the message */
computeExemple:
    push {r1,lr}         @ save  registres
    mov r1,r0
    bl computeMD5        @ call routine MD5

    ldr r0,iAdrszMessResult
    bl affichageMess
    mov r0,r1
    bl affichageMess
    ldr r0,iAdrszMessResult1
    bl affichageMess
    ldr r0, iAdrtbH
    bl displayMD5

100:
    pop {r1,pc}           @ restaur registers

/******************************************************************/
/*     compute MD5                         */
/******************************************************************/
/* r0 contains the address of the message */
computeMD5:
    push {r1-r12,lr}         @ save  registres
    ldr r1,iAdrsZoneTrav
    mov r2,#0                @ counter length
1:                           @ copy string in work area
    cmp r2,#ZWORKSIZE        @ maxi ?
    bge 99f                  @ error
    ldrb r3,[r0,r2]
    strb r3,[r1,r2]
    cmp r3,#0
    addne r2,r2,#1
    bne 1b
    lsl r6,r2,#3             @ initial message length in bits
    mov r3,#0b10000000       @ add bit 1 at end of string
    strb r3,[r1,r2]
    add r2,r2,#1             @ length in bytes
    lsl r4,r2,#3             @ length in bits
    mov r3,#0
2:
    lsr r5,r2,#6
    lsl r5,r5,#6
    sub r5,r2,r5
    cmp r5,#56
    beq 3f                   @ yes -> end add
    strb r3,[r1,r2]          @ add zero at message end
    add r2,#1                @ increment lenght bytes
    add r4,#8                @ increment length in bits
    b 2b
3:
    str r6,[r1,r2]           @ and store length at end
    add r5,r2,#4
    str r3,[r1,r5]           @ store zero in hight bits for 64 bits

    ldr r7,iAdrtbConstH      @ constantes H address
    ldr r4,iAdrtbH           @ start area H
    mov r5,#0
4:                           @ init array H with start constantes
    ldr r6,[r7,r5,lsl #2]    @ load constante
    str r6,[r4,r5,lsl #2]    @ and store
    add r5,r5,#1
    cmp r5,#4
    blt 4b
                             @ split into block of 64 bytes
    add r2,#4                @  TODO : à revoir
    lsr r4,r2,#6             @ blocks number

    ldr r0,iAdrtbH             @ variables H
    ldr r1,iAdrsZoneTrav
    ldr r5,iAdrtbConstK
    ldr r3,iAdrtbRotaR
    ldr r8,iAdrtbabcd
    mov r7,#0                @ n° de block et r1 contient l adresse zone de travail
5:                           @ begin loop of each block of 64 bytes
    add r2,r1,r7,lsl #6            @  compute block begin  indice * 4 * 16
    mov r6,#0                @ indice t
   /* COMPUTING THE MESSAGE DIGEST */
    /* r0  variables H address */
    /* r1  work area  */
    /* r2  block work area begin address  */
    /* r3  address constantes rotate */
    /* r4  block number  */
    /* r5  constance K address */
    /* r6  counter t */
    /* r7  block counter */
    /* r8  addresse variables a b c d   */
                                   @ init variable a b c d with variables H
    mov r10,#0
6:                                 @ loop init
    ldr r9,[r0,r10,lsl #2]         @ variables H
    str r9,[r8,r10,lsl #2]         @ variables a b c d
    add r10,r10,#1
    cmp r10,#4
    blt 6b

7:                                 @ loop begin
    cmp r6,#15
    bgt 8f
                                   @ cas 1 f := (b et c) ou ((non b) et d)
                                   @ g := i
    ldr r9,[r8,#var_b]
    ldr r10,[r8,#var_c]
    and r12,r10,r9
    mvn r9,r9
    ldr r10,[r8,#var_d]
    and r11,r9,r10
    orr r12,r12,r11                @ f
    mov r9,r6                      @ g
    b 11f
8:
    cmp r6,#31
    bgt 9f
                                   @ f := (d et b) ou ((non d) et c)
                                   @ g := (5×i + 1) mod 16
    ldr r9,[r8,#var_b]
    ldr r10,[r8,#var_d]
    and r12,r10,r9
    mvn r10,r10
    ldr r9,[r8,#var_c]
    and r11,r9,r10
    orr r12,r12,r11                @ f
    mov r9,#5
    mul r9,r6,r9
    add r9,r9,#1
    lsr r10,r9,#4
    lsl r10,r10,#4
    sub r9,r9,r10                  @ g

    b 11f
9:
    cmp r6,#47
    bgt 10f
                                   @ f := b xor c xor d
                                   @ g := (3×i + 5) mod 16
    ldr r9,[r8,#var_b]
    ldr r10,[r8,#var_c]
    eor r12,r10,r9
    ldr r10,[r8,#var_d]
    eor r12,r12,r10                @ f
    mov r9,#3
    mul r9,r6,r9
    add r9,r9,#5
    lsr r10,r9,#4
    lsl r10,r10,#4
    sub r9,r9,r10                  @ g
    b 11f
10:
                                   @ f := c xor (b ou (non d))
                                   @ g := (7×i) mod 16
    ldr r10,[r8,#var_d]
    mvn r12,r10
    ldr r10,[r8,#var_b]
    orr r12,r12,r10
    ldr r10,[r8,#var_c]
    eor r12,r12,r10                @ f
    mov r9,#7
    mul r9,r6,r9
    lsr r10,r9,#4
    lsl r10,r10,#4
    sub r9,r9,r10                  @ g

11:
    ldr r10,[r8,#var_d]
    mov r11,r10                    @ save old d
    ldr r10,[r8,#var_c]
    str r10,[r8,#var_d]            @ new d = c
    ldr r10,[r8,#var_b]
    str r10,[r8,#var_c]            @ new c = b
    ldr r10,[r8,#var_a]
    add r12,r12,r10                @ a + f
    ldr r10,[r2,r9,lsl #2]
    add r12,r12,r10                @ + valeur bloc g
    ldr r10,[r5,r6,lsl #2]
    add r12,r12,r10                @ + valeur constante K de i
    ldr r10,[r3,r6,lsl #2]         @ rotate left value
    rsb r10,r10,#32                @ compute right rotate
    ror r12,r12,r10
    ldr r10,[r8,#var_b]
    add r12,r12,r10
    str r12,[r8,#var_b]            @ new b
    str r11,[r8,#var_a]            @ new a = old d

    add r6,r6,#1
    cmp r6,#63
    ble 7b
                                   @ maj area H
    ldr r10,[r0]                   @ H0
    ldr r11,[r8,#var_a]
    add r10,r10,r11                @ + a
    str r10,[r0]
    ldr r10,[r0,#4]                @ H1
    ldr r11,[r8,#var_b]
    add r10,r10,r11                @ + b
    str r10,[r0,#4]
    ldr r10,[r0,#8]                @ H2
    ldr r11,[r8,#var_c]
    add r10,r10,r11                @ + c
    str r10,[r0,#8]
    ldr r10,[r0,#12]               @ H3
    ldr r11,[r8,#var_d]
    add r10,r10,r11                @ + d
    str r10,[r0,#12]

                                 @ loop other block
    add r7,r7,#1                 @ increment block
    cmp r7,r4                    @ maxi ?
    ble 5b

    mov r9,#0                    @ reverse bytes loop
12:
    ldr r10,[r0,r9,lsl #2]
    rev r10,r10                  @ reverse bytes
    str r10,[r0,r9,lsl #2]
    add r9,r9,#1
    cmp r9,#LGHASH / 4
    blt 12b
    mov r0,#0                    @ routine OK
    b 100f
99:                              @ size error
    ldr r0,iAdrszMessSizeError
    bl affichageMess
    mov r0,#-1                   @ error routine

100:
    pop {r1-r12,pc}              @ restaur registers
iAdrtbConstH:        .int tbConstH
iAdrtbConstK:        .int tbConstK
iAdrtbRotaR:         .int tbRotaR
iAdrtbH:             .int tbH
iAdrtbabcd:          .int tbabcd

/*************************************************/
/*     display hash  MD5                         */
/*************************************************/
/* r0 contains the address of hash  */
displayMD5:
    push {r1-r3,lr}                @ save  registres
    mov r3,r0
    mov r2,#0
1:
    ldr r0,[r3,r2,lsl #2]          @ load 4 bytes
    ldr r1,iAdrsZoneConv
    bl conversion16                @ conversion hexa
    ldr r0,iAdrsZoneConv
    bl affichageMess
    add r2,r2,#1
    cmp r2,#LGHASH / 4
    blt 1b                         @ and loop
    ldr r0,iAdrszCarriageReturn
    bl affichageMess               @ display message
100:
    pop {r1-r3,lr}                 @ restaur registers
    bx lr                          @ return
/***************************************************/
/*      ROUTINES INCLUDE                           */
/***************************************************/
.include "../affichage.inc"
Result for abc => 900150983CD24FB0D6963F7D28E17F72
Result for ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 => D174AB98D277D9F5A5611C2C9F419D9F
Result for abcdefghijklmnopqrstuvwxyz => C3FCD3D76192E4007DFB496CCA67E13B
Result for 12345678901234567890123456789012345678901234567890123456789012345678901234567890 => 57EDF4A22BE3C955AC49DA2E2107B67A
Program End ok.

implement an MD5 encoding for a given string. The codes also include an optional validation using test values from IETF RFC (1321) for MD5. However, due to known weaknesses of MD5, alternatives like SHA-256 or SHA-3 are recommended for production-grade cryptography. If the solution is a library, refer to MD5/Implementation for a scratch implementation.


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

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

/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessResult:        .ascii "Count : "
sMessValeur:        .fill 11, 1, ' '            @ size => 11
szCarriageReturn:   .asciz "\n"

/*********************************/
/* UnInitialized data            */
/*********************************/
.bss
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main
main:                                             @ entry of program
    mov r4,#0                                     @ loop indice
1:                                                @ begin loop
    mov r0,r4
    ldr r1,iAdrsMessValeur
    bl conversion8                                @ call conversion octal
    ldr r0,iAdrsMessResult
    bl affichageMess                              @ display message
    add r4,#1
    cmp r4,#64
    ble 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

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

/******************************************************************/
/*     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 octal                             */
/******************************************************************/
/* r0 contains value and r1 address area   */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes          */
.equ LGZONECAL,   10
conversion8:
    push {r1-r4,lr}                                 @ save registers
    mov r3,r1
    mov r2,#LGZONECAL

1:                                                  @ start loop
    mov r1,r0
    lsr r0,#3                                       @ / by 8
    sub r1,r0,lsl #3                                @ compute remainder r1 - (r0 * 8)
    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

generate a sequential count in octal, starting from zero and incrementing by one on each line until the program is terminated or the maximum numeric type value is reached.


@ Check whether the ASCII string in [r0] is a palindrome
@ Returns with zero flag set if palindrome.
palin:	mov	r1,r0		@ Find end of string
1:	ldrb	r2,[r1],#1	@ Grab character and increment pointer
	tst	r2,r2		@ Zero yet?
	bne	1b		@ If not try next byte
	sub	r1,r1,#2	@ Move R1 to last actual character.
2:	cmp	r0,r1		@ When R0 >= R1,
	cmpgt	r2,r2		@ make sure zero is set,
	bxeq	lr		@ and stop (the string is a palindrome).
	ldrb	r2,[r1],#-1	@ Grab [R1] (end) and decrement.
	ldrb	r3,[r0],#1	@ Grab [R0] (begin) and increment
	cmp	r2,r3		@ Are they equal?
	bxne	lr		@ If not, it's not a palindrome.
	b	2b		@ Otherwise, try next pair.

@ Try the function on a couple of strings
.global _start
_start:	ldr	r8,=words	@ Word pointer
1:	ldr	r9,[r8],#4	@ Grab word and move pointer
	tst	r9,r9		@ Null?
	moveq	r7,#1		@ Then we're done; syscall 1 = exit
	swieq	#0
	mov	r1,r9		@ Print the word
	bl	print
	mov	r0,r9		@ Test if the word is a palindrome
	bl	palin
	ldreq	r1,=yes		@ "Yes" if it is a palindrome
	ldrne	r1,=no		@ "No" if it's not a palindrome
	bl	print
	b	1b		@ Next word

@ Print zero-terminated string [r1] using Linux syscall
print:	push	{r7,lr}		@ Keep R7 and link register
	mov	r2,r1		@ Find end of string
1:	ldrb	r0,[r2],#1	@ Grab character and increment pointer
	tst	r0,r0		@ Zero yet?
	bne	1b		@ If not, keep going
	sub	r2,r2,r1	@ Calculate length of string (bytes to write)
	mov	r0,#1		@ Stdout = 1
	mov	r7,#4		@ Syscall 4 = write
	swi	#0		@ Make the syscall
	pop	{r7,lr}		@ Restore R7 and link register
	bx	lr

@ Strings
yes:	.asciz	": yes\n"	@ Output yes or no
no:	.asciz	": no\n"
w1:	.asciz	"rotor"		@ Words to test
w2:	.asciz	"racecar"
w3:	.asciz	"level"
w4:	.asciz	"redder"
w5:	.asciz	"rosetta"
words:	.word	w1,w2,w3,w4,w5,0

implement a function to check if a given sequence of characters is a palindrome. It also supports Unicode characters. Additionally, it includes a second function to detect inexact palindromes, ignoring white-space, punctuation, and case-sensitivity. It may also be useful for testing a function.


Library: STL

#include <stack>

#include <deque>
template <class T, class Sequence = std::deque<T> >
class stack {
  friend bool operator== (const stack&, const stack&);
  friend bool operator<  (const stack&, const stack&);
public:
  typedef typename Sequence::value_type      value_type;
  typedef typename Sequence::size_type       size_type;
  typedef          Sequence                  container_type;
  typedef typename Sequence::reference       reference;
  typedef typename Sequence::const_reference const_reference;
protected:
  Sequence seq;
public:
  stack() : seq() {}
  explicit stack(const Sequence& s0) : seq(s0) {}
  bool empty() const { return seq.empty(); }
  size_type size() const { return seq.size(); }
  reference top() { return seq.back(); }
  const_reference top() const { return seq.back(); }
  void push(const value_type& x) { seq.push_back(x); }
  void pop() { seq.pop_back(); }
};

template <class T, class Sequence>
bool operator==(const stack<T,Sequence>& x, const stack<T,Sequence>& y)
{
  return x.seq == y.seq;
}
template <class T, class Sequence>
bool operator<(const stack<T,Sequence>& x, const stack<T,Sequence>& y)
{
  return x.seq < y.seq;
}

template <class T, class Sequence>
bool operator!=(const stack<T,Sequence>& x, const stack<T,Sequence>& y)
{
  return !(x == y);
}
template <class T, class Sequence>
bool operator>(const stack<T,Sequence>& x, const stack<T,Sequence>& y)
{
  return y < x;
}
template <class T, class Sequence>
bool operator<=(const stack<T,Sequence>& x, const stack<T,Sequence>& y)
{
  return !(y < x);
}
template <class T, class Sequence>
bool operator>=(const stack<T,Sequence>& x, const stack<T,Sequence>& y)
{
  return !(x < y);
}

implement a stack data structure with basic operations such as push, pop, and empty. The stack follows a last in, first out (LIFO) access policy and allows access to the topmost element without modification. The stack is commonly used in programming for resource management, implementing local variables in recursive subprograms, and in various algorithms. The C++ standard library provides a ready-made stack class for use.


#include <iostream>

int main()
{
        unsigned int a = 1, b = 1;
        unsigned int target = 48;
        for(unsigned int n = 3; n <= target; ++n)
        {
                unsigned int fib = a + b;
                std::cout << "F("<< n << ") = " << fib << std::endl;
                a = b;
                b = fib;
        }

        return 0;
}

Library: GMP

#include <iostream>
#include <gmpxx.h>

int main()
{
        mpz_class a = mpz_class(1), b = mpz_class(1);
        mpz_class target = mpz_class(100);
        for(mpz_class n = mpz_class(3); n <= target; ++n)
        {
                mpz_class fib = b + a;
                if ( fib < b )
                {
                        std::cout << "Overflow at " << n << std::endl;
                        break;
                }
                std::cout << "F("<< n << ") = " << fib << std::endl;
                a = b;
                b = fib;
        }
        return 0;
}

#include <algorithm>
#include <vector>
#include <functional>
#include <iostream>

unsigned int fibonacci(unsigned int n) {
  if (n == 0) return 0;
  std::vector<int> v(n+1);
  v[1] = 1;
  transform(v.begin(), v.end()-2, v.begin()+1, v.begin()+2, std::plus<int>());
  // "v" now contains the Fibonacci sequence from 0 up
  return v[n];
}

#include <numeric>
#include <vector>
#include <functional>
#include <iostream>

unsigned int fibonacci(unsigned int n) {
  if (n == 0) return 0;
  std::vector<int> v(n, 1);
  adjacent_difference(v.begin(), v.end()-1, v.begin()+1, std::plus<int>());
  // "array" now contains the Fibonacci sequence from 1 up
  return v[n-1];
}

#include <iostream>

template <int n> struct fibo
{
    enum {value=fibo<n-1>::value+fibo<n-2>::value};
};

template <> struct fibo<0>
{
    enum {value=0};
};

template <> struct fibo<1>
{
    enum {value=1};
};

int main(int argc, char const *argv[])
{
    std::cout<<fibo<12>::value<<std::endl;
    std::cout<<fibo<46>::value<<std::endl;
    return 0;
}

#include <iostream>

inline void fibmul(int* f, int* g)
{
  int tmp = f[0]*g[0] + f[1]*g[1];
  f[1] = f[0]*g[1] + f[1]*(g[0] + g[1]);
  f[0] = tmp;
}

int fibonacci(int n)
{
  int f[] = { 1, 0 };
  int g[] = { 0, 1 };
  while (n > 0)
  {
    if (n & 1) // n odd
    {
      fibmul(f, g);
      --n;
    }
    else
    {
      fibmul(g, g);
      n >>= 1;
    }
  }
  return f[1];
}

int main()
{
  for (int i = 0; i < 20; ++i)
    std::cout << fibonacci(i) << " ";
  std::cout << std::endl;
}

The code generates the nth Fibonacci number, either iteratively or recursively. It optionally supports negative n values by using an inverse definition. The code can overflow if unsigned int is used and n is greater than 48. Different versions of the code include using transform, adjacent_difference, compile-time computation with metaprogramming, and fast exponentiation. There's also a version that represents the nth Fibonacci number as a Zeckendorf number.


#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>
#include <iostream>

int main() {
  std::vector<int> ary;
  for (int i = 0; i < 10; i++)
    ary.push_back(i);
  std::vector<int> evens;
  std::remove_copy_if(ary.begin(), ary.end(), back_inserter(evens),
                      std::bind2nd(std::modulus<int>(), 2)); // filter copy
  std::copy(evens.begin(), evens.end(),
            std::ostream_iterator<int>(std::cout, "\n"));

  return 0;
}

Works with: C++11
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>

using namespace std;

int main() {
  vector<int> ary = {1, 2, 3, 4, 5, 6, 7, 8, 9};
  vector<int> evens;

  copy_if(ary.begin(), ary.end(), back_inserter(evens),
      [](int i) { return i % 2 == 0; });

  // print result
  copy(evens.begin(), evens.end(), ostream_iterator<int>(cout, "\n"));
}

select certain elements from an array into a new array in a generic way, specifically all even numbers. Optionally, it also provides a destructive filtering solution that modifies the original array instead of creating a new one.


#include <iostream>
#include <string>

int main()
{
  std::string s = "0123456789";

  int const n = 3;
  int const m = 4;
  char const c = '2';
  std::string const sub = "456";

  std::cout << s.substr(n, m)<< "\n";
  std::cout << s.substr(n) << "\n";
  std::cout << s.substr(0, s.size()-1) << "\n";
  std::cout << s.substr(s.find(c), m) << "\n";
  std::cout << s.substr(s.find(sub), m) << "\n";
}

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


#include <string>
#include <iostream>
#include <algorithm>

int main() {
  std::string s;
  std::getline(std::cin, s);
  std::reverse(s.begin(), s.end()); // modifies s
  std::cout << s << '\n';
}

Reverses a given string while preserving Unicode combining characters. For instance, it transforms "asdf" to "fdsa" and "as⃝df̅" to "f̅ds⃝a".


#include <iostream>
#include <string>

using namespace std;

class playfair
{
public:
    void doIt( string k, string t, bool ij, bool e )
    {
	createGrid( k, ij ); getTextReady( t, ij, e );
	if( e ) doIt( 1 ); else doIt( -1 );
	display();
    }

private:
    void doIt( int dir )
    {
	int a, b, c, d; string ntxt;
	for( string::const_iterator ti = _txt.begin(); ti != _txt.end(); ti++ )
	{
	    if( getCharPos( *ti++, a, b ) )
		if( getCharPos( *ti, c, d ) )
		{
		    if( a == c )     { ntxt += getChar( a, b + dir ); ntxt += getChar( c, d + dir ); }
		    else if( b == d ){ ntxt += getChar( a + dir, b ); ntxt += getChar( c + dir, d ); }
		    else             { ntxt += getChar( c, b ); ntxt += getChar( a, d ); }
		}
	}
	_txt = ntxt;
    }

    void display()
    {
	cout << "\n\n OUTPUT:\n=========" << endl;
	string::iterator si = _txt.begin(); int cnt = 0;
	while( si != _txt.end() )
	{
	    cout << *si; si++; cout << *si << " "; si++;
	    if( ++cnt >= 26 ) cout << endl, cnt = 0;
	}
	cout << endl << endl;
    }

    char getChar( int a, int b )
    {
	return _m[ (b + 5) % 5 ][ (a + 5) % 5 ];
    }

    bool getCharPos( char l, int &a, int &b )
    {
	for( int y = 0; y < 5; y++ )
	    for( int x = 0; x < 5; x++ )
		if( _m[y][x] == l )
		{ a = x; b = y; return true; }

	return false;
    }

    void getTextReady( string t, bool ij, bool e )
    {
	for( string::iterator si = t.begin(); si != t.end(); si++ )
	{
	    *si = toupper( *si ); if( *si < 65 || *si > 90 ) continue;
	    if( *si == 'J' && ij ) *si = 'I';
	    else if( *si == 'Q' && !ij ) continue;
	    _txt += *si;
	}
	if( e )
	{
	    string ntxt = ""; size_t len = _txt.length();
	    for( size_t x = 0; x < len; x += 2 )
	    {
		ntxt += _txt[x];
		if( x + 1 < len )
		{
		    if( _txt[x] == _txt[x + 1] ) ntxt += 'X';
		    ntxt += _txt[x + 1];
		}
	    }
	    _txt = ntxt;
	}
	if( _txt.length() & 1 ) _txt += 'X';
    }

    void createGrid( string k, bool ij )
    {
	if( k.length() < 1 ) k = "KEYWORD";
	k += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string nk = "";
	for( string::iterator si = k.begin(); si != k.end(); si++ )
	{
	    *si = toupper( *si ); if( *si < 65 || *si > 90 ) continue;
	    if( ( *si == 'J' && ij ) || ( *si == 'Q' && !ij ) )continue;
	    if( nk.find( *si ) == -1 ) nk += *si;
	}
	copy( nk.begin(), nk.end(), &_m[0][0] );
    }

    string _txt; char _m[5][5];
};

int main( int argc, char* argv[] )
{
    string key, i, txt; bool ij, e;
    cout << "(E)ncode or (D)ecode? "; getline( cin, i ); e = ( i[0] == 'e' || i[0] == 'E' );
    cout << "Enter a en/decryption key: "; getline( cin, key );
    cout << "I <-> J (Y/N): "; getline( cin, i ); ij = ( i[0] == 'y' || i[0] == 'Y' );
    cout << "Enter the text: "; getline( cin, txt );
    playfair pf; pf.doIt( key, txt, ij, e ); return system( "pause" );
}

Implement the Playfair cipher for both encryption and decryption. It allows the user to choose whether 'J' equals 'I' or there's no 'Q' in the alphabet. The resulting encrypted and decrypted messages are presented in capitalized digraphs, separated by spaces.


#include <iostream>
#include <vector>
#include <string>
#include <list>

#include <limits> // for numeric_limits

#include <set>
#include <utility> // for pair
#include <algorithm>
#include <iterator>

typedef int vertex_t;
typedef double weight_t;

const weight_t max_weight = std::numeric_limits<double>::infinity();

struct neighbor {
    vertex_t target;
    weight_t weight;
    neighbor(vertex_t arg_target, weight_t arg_weight)
        : target(arg_target), weight(arg_weight) { }
};

typedef std::vector<std::vector<neighbor> > adjacency_list_t;

void DijkstraComputePaths(vertex_t source,
                          const adjacency_list_t &adjacency_list,
                          std::vector<weight_t> &min_distance,
                          std::vector<vertex_t> &previous)
{
    int n = adjacency_list.size();
    min_distance.clear();
    min_distance.resize(n, max_weight);
    min_distance[source] = 0;
    previous.clear();
    previous.resize(n, -1);
    std::set<std::pair<weight_t, vertex_t> > vertex_queue;
    vertex_queue.insert(std::make_pair(min_distance[source], source));

    while (!vertex_queue.empty())
    {
        weight_t dist = vertex_queue.begin()->first;
        vertex_t u = vertex_queue.begin()->second;
        vertex_queue.erase(vertex_queue.begin());

        // Visit each edge exiting u
	const std::vector<neighbor> &neighbors = adjacency_list[u];
        for (std::vector<neighbor>::const_iterator neighbor_iter = neighbors.begin();
             neighbor_iter != neighbors.end();
             neighbor_iter++)
        {
            vertex_t v = neighbor_iter->target;
            weight_t weight = neighbor_iter->weight;
            weight_t distance_through_u = dist + weight;
	    if (distance_through_u < min_distance[v]) {
	        vertex_queue.erase(std::make_pair(min_distance[v], v));

	        min_distance[v] = distance_through_u;
	        previous[v] = u;
	        vertex_queue.insert(std::make_pair(min_distance[v], v));

	    }

        }
    }
}

std::list<vertex_t> DijkstraGetShortestPathTo(
    vertex_t vertex, const std::vector<vertex_t> &previous)
{
    std::list<vertex_t> path;
    for ( ; vertex != -1; vertex = previous[vertex])
        path.push_front(vertex);
    return path;
}

int main()
{
    // remember to insert edges both ways for an undirected graph
    adjacency_list_t adjacency_list(6);
    // 0 = a
    adjacency_list[0].push_back(neighbor(1, 7));
    adjacency_list[0].push_back(neighbor(2, 9));
    adjacency_list[0].push_back(neighbor(5, 14));
    // 1 = b
    adjacency_list[1].push_back(neighbor(0, 7));
    adjacency_list[1].push_back(neighbor(2, 10));
    adjacency_list[1].push_back(neighbor(3, 15));
    // 2 = c
    adjacency_list[2].push_back(neighbor(0, 9));
    adjacency_list[2].push_back(neighbor(1, 10));
    adjacency_list[2].push_back(neighbor(3, 11));
    adjacency_list[2].push_back(neighbor(5, 2));
    // 3 = d
    adjacency_list[3].push_back(neighbor(1, 15));
    adjacency_list[3].push_back(neighbor(2, 11));
    adjacency_list[3].push_back(neighbor(4, 6));
    // 4 = e
    adjacency_list[4].push_back(neighbor(3, 6));
    adjacency_list[4].push_back(neighbor(5, 9));
    // 5 = f
    adjacency_list[5].push_back(neighbor(0, 14));
    adjacency_list[5].push_back(neighbor(2, 2));
    adjacency_list[5].push_back(neighbor(4, 9));

    std::vector<weight_t> min_distance;
    std::vector<vertex_t> previous;
    DijkstraComputePaths(0, adjacency_list, min_distance, previous);
    std::cout << "Distance from 0 to 4: " << min_distance[4] << std::endl;
    std::list<vertex_t> path = DijkstraGetShortestPathTo(4, previous);
    std::cout << "Path : ";
    std::copy(path.begin(), path.end(), std::ostream_iterator<vertex_t>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}

#include <iostream>
#include <vector>
#include <string>
#include <list>

#include <limits> // for numeric_limits

#include <queue>
#include <utility> // for pair
#include <algorithm>
#include <iterator>

typedef int vertex_t;
typedef double weight_t;

const weight_t max_weight = std::numeric_limits<double>::infinity();

struct neighbor {
    vertex_t target;
    weight_t weight;
    neighbor(vertex_t arg_target, weight_t arg_weight)
        : target(arg_target), weight(arg_weight) { }
};

typedef std::vector<std::vector<neighbor> > adjacency_list_t;
typedef std::pair<weight_t, vertex_t> weight_vertex_pair_t;

void DijkstraComputePaths(vertex_t source,
                          const adjacency_list_t &adjacency_list,
                          std::vector<weight_t> &min_distance,
                          std::vector<vertex_t> &previous)
{
    int n = adjacency_list.size();
    min_distance.clear();
    min_distance.resize(n, max_weight);
    min_distance[source] = 0;
    previous.clear();
    previous.resize(n, -1);
    // we use greater instead of less to turn max-heap into min-heap
    std::priority_queue<weight_vertex_pair_t,
			std::vector<weight_vertex_pair_t>,
			std::greater<weight_vertex_pair_t> > vertex_queue;
    vertex_queue.push(std::make_pair(min_distance[source], source));

    while (!vertex_queue.empty())
    {
        weight_t dist = vertex_queue.top().first;
        vertex_t u = vertex_queue.top().second;
        vertex_queue.pop();

	// Because we leave old copies of the vertex in the priority queue
	// (with outdated higher distances), we need to ignore it when we come
	// across it again, by checking its distance against the minimum distance
	if (dist > min_distance[u])
	    continue;

        // Visit each edge exiting u
	const std::vector<neighbor> &neighbors = adjacency_list[u];
        for (std::vector<neighbor>::const_iterator neighbor_iter = neighbors.begin();
             neighbor_iter != neighbors.end();
             neighbor_iter++)
        {
            vertex_t v = neighbor_iter->target;
            weight_t weight = neighbor_iter->weight;
            weight_t distance_through_u = dist + weight;
	    if (distance_through_u < min_distance[v]) {
	        min_distance[v] = distance_through_u;
	        previous[v] = u;
	        vertex_queue.push(std::make_pair(min_distance[v], v));

	    }

        }
    }
}

std::list<vertex_t> DijkstraGetShortestPathTo(
    vertex_t vertex, const std::vector<vertex_t> &previous)
{
    std::list<vertex_t> path;
    for ( ; vertex != -1; vertex = previous[vertex])
        path.push_front(vertex);
    return path;
}

int main()
{
    // remember to insert edges both ways for an undirected graph
    adjacency_list_t adjacency_list(6);
    // 0 = a
    adjacency_list[0].push_back(neighbor(1, 7));
    adjacency_list[0].push_back(neighbor(2, 9));
    adjacency_list[0].push_back(neighbor(5, 14));
    // 1 = b
    adjacency_list[1].push_back(neighbor(0, 7));
    adjacency_list[1].push_back(neighbor(2, 10));
    adjacency_list[1].push_back(neighbor(3, 15));
    // 2 = c
    adjacency_list[2].push_back(neighbor(0, 9));
    adjacency_list[2].push_back(neighbor(1, 10));
    adjacency_list[2].push_back(neighbor(3, 11));
    adjacency_list[2].push_back(neighbor(5, 2));
    // 3 = d
    adjacency_list[3].push_back(neighbor(1, 15));
    adjacency_list[3].push_back(neighbor(2, 11));
    adjacency_list[3].push_back(neighbor(4, 6));
    // 4 = e
    adjacency_list[4].push_back(neighbor(3, 6));
    adjacency_list[4].push_back(neighbor(5, 9));
    // 5 = f
    adjacency_list[5].push_back(neighbor(0, 14));
    adjacency_list[5].push_back(neighbor(2, 2));
    adjacency_list[5].push_back(neighbor(4, 9));

    std::vector<weight_t> min_distance;
    std::vector<vertex_t> previous;
    DijkstraComputePaths(0, adjacency_list, min_distance, previous);
    std::cout << "Distance from 0 to 4: " << min_distance[4] << std::endl;
    std::list<vertex_t> path = DijkstraGetShortestPathTo(4, previous);
    std::cout << "Path : ";
    std::copy(path.begin(), path.end(), std::ostream_iterator<vertex_t>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}

The code implements Dijkstra's algorithm to find the shortest path between a given source node and all other nodes in a graph. The graph is represented by an adjacency matrix or list and a start node. The algorithm is applied on a directed and weighted graph with non-negative edge path costs. The output is a set of edges depicting the shortest path to each destination node. The code also includes functionality to interpret the output and provide the shortest path from the source node to specific nodes. The algorithm is optimized using a self-balancing binary search tree for the priority queue of vertices, ensuring a time complexity of O(E log V).


#include <algorithm>
#include <iostream>

/* AVL node */
template <class T>
class AVLnode {
public:
    T key;
    int balance;
    AVLnode *left, *right, *parent;

    AVLnode(T k, AVLnode *p) : key(k), balance(0), parent(p),
                        left(NULL), right(NULL) {}

    ~AVLnode() {
        delete left;
        delete right;
    }
};

/* AVL tree */
template <class T>
class AVLtree {
public:
    AVLtree(void);
    ~AVLtree(void);
    bool insert(T key);
    void deleteKey(const T key);
    void printBalance();

private:
    AVLnode<T> *root;

    AVLnode<T>* rotateLeft          ( AVLnode<T> *a );
    AVLnode<T>* rotateRight         ( AVLnode<T> *a );
    AVLnode<T>* rotateLeftThenRight ( AVLnode<T> *n );
    AVLnode<T>* rotateRightThenLeft ( AVLnode<T> *n );
    void rebalance                  ( AVLnode<T> *n );
    int height                      ( AVLnode<T> *n );
    void setBalance                 ( AVLnode<T> *n );
    void printBalance               ( AVLnode<T> *n );
};

/* AVL class definition */
template <class T>
void AVLtree<T>::rebalance(AVLnode<T> *n) {
    setBalance(n);

    if (n->balance == -2) {
        if (height(n->left->left) >= height(n->left->right))
            n = rotateRight(n);
        else
            n = rotateLeftThenRight(n);
    }
    else if (n->balance == 2) {
        if (height(n->right->right) >= height(n->right->left))
            n = rotateLeft(n);
        else
            n = rotateRightThenLeft(n);
    }

    if (n->parent != NULL) {
        rebalance(n->parent);
    }
    else {
        root = n;
    }
}

template <class T>
AVLnode<T>* AVLtree<T>::rotateLeft(AVLnode<T> *a) {
    AVLnode<T> *b = a->right;
    b->parent = a->parent;
    a->right = b->left;

    if (a->right != NULL)
        a->right->parent = a;

    b->left = a;
    a->parent = b;

    if (b->parent != NULL) {
        if (b->parent->right == a) {
            b->parent->right = b;
        }
        else {
            b->parent->left = b;
        }
    }

    setBalance(a);
    setBalance(b);
    return b;
}

template <class T>
AVLnode<T>* AVLtree<T>::rotateRight(AVLnode<T> *a) {
    AVLnode<T> *b = a->left;
    b->parent = a->parent;
    a->left = b->right;

    if (a->left != NULL)
        a->left->parent = a;

    b->right = a;
    a->parent = b;

    if (b->parent != NULL) {
        if (b->parent->right == a) {
            b->parent->right = b;
        }
        else {
            b->parent->left = b;
        }
    }

    setBalance(a);
    setBalance(b);
    return b;
}

template <class T>
AVLnode<T>* AVLtree<T>::rotateLeftThenRight(AVLnode<T> *n) {
    n->left = rotateLeft(n->left);
    return rotateRight(n);
}

template <class T>
AVLnode<T>* AVLtree<T>::rotateRightThenLeft(AVLnode<T> *n) {
    n->right = rotateRight(n->right);
    return rotateLeft(n);
}

template <class T>
int AVLtree<T>::height(AVLnode<T> *n) {
    if (n == NULL)
        return -1;
    return 1 + std::max(height(n->left), height(n->right));
}

template <class T>
void AVLtree<T>::setBalance(AVLnode<T> *n) {
    n->balance = height(n->right) - height(n->left);
}

template <class T>
void AVLtree<T>::printBalance(AVLnode<T> *n) {
    if (n != NULL) {
        printBalance(n->left);
        std::cout << n->balance << " ";
        printBalance(n->right);
    }
}

template <class T>
AVLtree<T>::AVLtree(void) : root(NULL) {}

template <class T>
AVLtree<T>::~AVLtree(void) {
    delete root;
}

template <class T>
bool AVLtree<T>::insert(T key) {
    if (root == NULL) {
        root = new AVLnode<T>(key, NULL);
    }
    else {
        AVLnode<T>
            *n = root,
            *parent;

        while (true) {
            if (n->key == key)
                return false;

            parent = n;

            bool goLeft = n->key > key;
            n = goLeft ? n->left : n->right;

            if (n == NULL) {
                if (goLeft) {
                    parent->left = new AVLnode<T>(key, parent);
                }
                else {
                    parent->right = new AVLnode<T>(key, parent);
                }

                rebalance(parent);
                break;
            }
        }
    }

    return true;
}

template <class T>
void AVLtree<T>::deleteKey(const T delKey) {
    if (root == NULL)
        return;

    AVLnode<T>
        *n       = root,
        *parent  = root,
        *delNode = NULL,
        *child   = root;

    while (child != NULL) {
        parent = n;
        n = child;
        child = delKey >= n->key ? n->right : n->left;
        if (delKey == n->key)
            delNode = n;
    }

    if (delNode != NULL) {
        delNode->key = n->key;

        child = n->left != NULL ? n->left : n->right;

        if (root->key == delKey) {
            root = child;
        }
        else {
            if (parent->left == n) {
                parent->left = child;
            }
            else {
                parent->right = child;
            }

            rebalance(parent);
        }
    }
}

template <class T>
void AVLtree<T>::printBalance() {
    printBalance(root);
    std::cout << std::endl;
}

int main(void)
{
    AVLtree<int> t;

    std::cout << "Inserting integer values 1 to 10" << std::endl;
    for (int i = 1; i <= 10; ++i)
        t.insert(i);

    std::cout << "Printing balance: ";
    t.printBalance();
}

implement an AVL tree, a self-balancing binary search tree, ensuring the heights of two child subtrees of any node differ by at most one. The codes provide basic operations including lookup, insertion, and deletion, all of which take O(log n) time. The tree is rebalanced as necessary through tree rotations. Duplicate node keys are not allowed. The implementation is compared with red-black trees for performance analysis.


Works with: C++11
#include <iostream>
#include <cmath>
#include <tuple>

struct point { double x, y; };

bool operator==(const point& lhs, const point& rhs)
{ return std::tie(lhs.x, lhs.y) == std::tie(rhs.x, rhs.y); }

enum result_category { NONE, ONE_COINCEDENT, ONE_DIAMETER, TWO, INFINITE };

using result_t = std::tuple<result_category, point, point>;

double distance(point l, point r)
{ return std::hypot(l.x - r.x, l.y - r.y); }

result_t find_circles(point p1, point p2, double r)
{
    point ans1 { 1/0., 1/0.}, ans2 { 1/0., 1/0.};
    if (p1 == p2) {
        if(r == 0.) return std::make_tuple(ONE_COINCEDENT, p1,   p2  );
        else        return std::make_tuple(INFINITE,       ans1, ans2);
    }
    point center { p1.x/2 + p2.x/2, p1.y/2 + p2.y/2};
    double half_distance = distance(center, p1);
    if(half_distance > r)      return std::make_tuple(NONE,         ans1,   ans2);
    if(half_distance - r == 0) return std::make_tuple(ONE_DIAMETER, center, ans2);
    double root = sqrt(pow(r, 2.l) - pow(half_distance, 2.l)) / distance(p1, p2);
    ans1.x = center.x + root * (p1.y - p2.y);
    ans1.y = center.y + root * (p2.x - p1.x);
    ans2.x = center.x - root * (p1.y - p2.y);
    ans2.y = center.y - root * (p2.x - p1.x);
    return std::make_tuple(TWO, ans1, ans2);
}

void print(result_t result, std::ostream& out = std::cout)
{
    point r1, r2; result_category res;
    std::tie(res, r1, r2) = result;
    switch(res) {
      case NONE:
        out << "There are no solutions, points are too far away\n"; break;
      case ONE_COINCEDENT: case ONE_DIAMETER:
        out << "Only one solution: " << r1.x << ' ' << r1.y << '\n'; break;
      case INFINITE:
        out << "Infinitely many circles can be drawn\n"; break;
      case TWO:
        out << "Two solutions: " << r1.x << ' ' << r1.y << " and " << r2.x << ' ' << r2.y << '\n'; break;
    }
}

int main()
{
    constexpr int size = 5;
    const point points[size*2] = {
        {0.1234, 0.9876}, {0.8765, 0.2345}, {0.0000, 2.0000}, {0.0000, 0.0000},
        {0.1234, 0.9876}, {0.1234, 0.9876}, {0.1234, 0.9876}, {0.8765, 0.2345},
        {0.1234, 0.9876}, {0.1234, 0.9876}
    };
    const double radius[size] = {2., 1., 2., .5, 0.};

    for(int i = 0; i < size; ++i)
        print(find_circles(points[i*2], points[i*2 + 1], radius[i]));
}

"Function to calculate two possible circles given two points and a radius in 2D space. The function handles special cases such as when radius is zero, points are coincident, points form a diameter, or points are too distant. The function returns the circles or a special indication when two equal or distinct circles cannot be returned."


implement the main step of the GOST 28147-89 encryption algorithm, which takes a 64-bit block of text and one of the eight 32-bit encryption key elements, uses the replacement table (BS), and returns an encrypted block.


#include <iostream>
#include <ctime>
#include <cstdlib>

int main(){
	srand(time(NULL)); // randomize seed
	while(true){
		const int a = rand() % 20; // biased towards lower numbers if RANDMAX % 20 > 0
		std::cout << a << std::endl;
		if(a == 10)
			break;
		const int b = rand() % 20;
		std::cout << b << std::endl;
	}
	return 0;
}

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


#include <iostream>
#include <cstdint>

typedef uint64_t integer;

integer bit_count(integer n) {
    integer count = 0;
    for (; n > 0; count++)
        n >>= 1;
    return count;
}

integer mod_pow(integer p, integer n) {
    integer square = 1;
    for (integer bits = bit_count(p); bits > 0; square %= n) {
        square *= square;
        if (p & (1 << --bits))
            square <<= 1;
    }
    return square;
}

bool is_prime(integer n) {
    if (n < 2)
        return false;
    if (n % 2 == 0)
        return n == 2;
    for (integer p = 3; p * p <= n; p += 2)
        if (n % p == 0)
            return false;
    return true;
}

integer find_mersenne_factor(integer p) {
    for (integer k = 0, q = 1;;) {
        q = 2 * ++k * p + 1;
        if ((q % 8 == 1 || q % 8 == 7) && mod_pow(p, q) == 1 && is_prime(q))
            return q;
    }
    return 0;
}

int main() {
    std::cout << find_mersenne_factor(929) << std::endl;
    return 0;
}

implement a method to find a factor of a Mersenne number (in this case, M929). The method uses efficient algorithms to determine if a number divides 2P-1, including a self-implemented modPow operation. It also incorporates properties of Mersenne numbers to refine the process, such as the form of any factor q of 2P-1 and the conditions that q must meet. The method stops when 2kP+1 > sqrt(N). It only works on Mersenne numbers where P is prime.


Library: LibXML
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <utility>
#include <vector>

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlerror.h>
#include <libxml/xmlstring.h>
#include <libxml/xmlversion.h>
#include <libxml/xpath.h>

#ifndef LIBXML_XPATH_ENABLED
#   error libxml was not configured with XPath support
#endif

// Because libxml2 is a C library, we need a couple things to make it work
// well with modern C++:
//   1) a ScopeGuard-like type to handle cleanup functions; and
//   2) an exception type that transforms the library's errors.

// ScopeGuard-like type to handle C library cleanup functions.
template <typename F>
class [[nodiscard]] scope_exit
{
public:
    // C++20: Constructor can (and should) be [[nodiscard]].
    /*[[nodiscard]]*/ constexpr explicit scope_exit(F&& f) :
        f_{std::move(f)}
    {}

    ~scope_exit()
    {
        f_();
    }

    // Non-copyable, non-movable.
    scope_exit(scope_exit const&) = delete;
    scope_exit(scope_exit&&) = delete;
    auto operator=(scope_exit const&) -> scope_exit& = delete;
    auto operator=(scope_exit&&) -> scope_exit& = delete;

private:
    F f_;
};

// Exception that gets last libxml2 error.
class libxml_error : public std::runtime_error
{
public:
    libxml_error() : libxml_error(std::string{}) {}

    explicit libxml_error(std::string message) :
        std::runtime_error{make_message_(std::move(message))}
    {}

private:
    static auto make_message_(std::string message) -> std::string
    {
        if (auto const last_error = ::xmlGetLastError(); last_error)
        {
            if (not message.empty())
                message += ": ";
            message += last_error->message;
        }

        return message;
    }
};

auto main() -> int
{
    try
    {
        // Initialize libxml.
        ::xmlInitParser();
        LIBXML_TEST_VERSION
        auto const libxml_cleanup = scope_exit{[] { ::xmlCleanupParser(); }};

        // Load and parse XML document.
        auto const doc = ::xmlParseFile("test.xml");
        if (not doc)
            throw libxml_error{"failed to load document"};
        auto const doc_cleanup = scope_exit{[doc] { ::xmlFreeDoc(doc); }};

        // Create XPath context for document.
        auto const xpath_context = ::xmlXPathNewContext(doc);
        if (not xpath_context)
            throw libxml_error{"failed to create XPath context"};
        auto const xpath_context_cleanup = scope_exit{[xpath_context]
            { ::xmlXPathFreeContext(xpath_context); }};

        // Task 1 ============================================================
        {
            std::cout << "Task 1:\n";

            auto const xpath =
                reinterpret_cast<::xmlChar const*>(u8"//item[1]");

            // Create XPath object (same for every task).
            auto xpath_obj = ::xmlXPathEvalExpression(xpath, xpath_context);
            if (not xpath_obj)
                throw libxml_error{"failed to evaluate XPath"};
            auto const xpath_obj_cleanup = scope_exit{[xpath_obj]
                { ::xmlXPathFreeObject(xpath_obj); }};

            // 'result' a xmlNode* to the desired node, or nullptr if it
            // doesn't exist. If not nullptr, the node is owned by 'doc'.
            auto const result = xmlXPathNodeSetItem(xpath_obj->nodesetval, 0);
            if (result)
                std::cout << '\t' << "node found" << '\n';
            else
                std::cout << '\t' << "node not found" << '\n';
        }

        // Task 2 ============================================================
        {
            std::cout << "Task 2:\n";

            auto const xpath =
                reinterpret_cast<::xmlChar const*>(u8"//price/text()");

            // Create XPath object (same for every task).
            auto xpath_obj = ::xmlXPathEvalExpression(xpath, xpath_context);
            if (not xpath_obj)
                throw libxml_error{"failed to evaluate XPath"};
            auto const xpath_obj_cleanup = scope_exit{[xpath_obj]
                { ::xmlXPathFreeObject(xpath_obj); }};

            // Printing the results.
            auto const count =
                xmlXPathNodeSetGetLength(xpath_obj->nodesetval);
            for (auto i = decltype(count){0}; i < count; ++i)
            {
                auto const node =
                    xmlXPathNodeSetItem(xpath_obj->nodesetval, i);
                assert(node);

                auto const content = XML_GET_CONTENT(node);
                assert(content);

                // Note that reinterpret_cast here is a Bad Idea, because
                // 'content' is UTF-8 encoded, which may or may not be the
                // encoding cout expects. A *PROPER* solution would translate
                // content to the correct encoding (or at least verify that
                // UTF-8 *is* the correct encoding).
                //
                // But this "works" well enough for illustration.
                std::cout << "\n\t" << reinterpret_cast<char const*>(content);
            }

            std::cout << '\n';
        }

        // Task 3 ============================================================
        {
            std::cout << "Task 3:\n";

            auto const xpath =
                reinterpret_cast<::xmlChar const*>(u8"//name");

            // Create XPath object (same for every task).
            auto xpath_obj = ::xmlXPathEvalExpression(xpath, xpath_context);
            if (not xpath_obj)
                throw libxml_error{"failed to evaluate XPath"};
            auto const xpath_obj_cleanup = scope_exit{[xpath_obj]
                { ::xmlXPathFreeObject(xpath_obj); }};

            // 'results' is a vector of pointers to the result nodes. The
            // nodes pointed to are owned by 'doc'.
            auto const results = [ns=xpath_obj->nodesetval]()
            {
                auto v = std::vector<::xmlNode*>{};
                if (ns && ns->nodeTab)
                    v.assign(ns->nodeTab, ns->nodeTab + ns->nodeNr);
                return v;
            }();
            std::cout << '\t' << "set of " << results.size()
                << " node(s) found" << '\n';
        }
    }
    catch (std::exception const& x)
    {
        std::cerr << "ERROR: " << x.what() << '\n';
        return EXIT_FAILURE;
    }
}

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


#include <set>
#include <iostream>
#include <iterator>
#include <algorithm>

namespace set_display {
template <class T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& set)
{
    os << '[';
    if (!set.empty()) {
        std::copy(set.begin(), --set.end(), std::ostream_iterator<T>(os, ", "));
        os << *--set.end();
    }
    return os << ']';
}
}

template <class T>
bool contains(const std::set<T>& set, const T& key)
{
    return set.count(key) != 0;
}

template <class T>
std::set<T> set_union(const std::set<T>& a, const std::set<T>& b)
{
    std::set<T> result;
    std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::inserter(result, result.end()));
    return result;
}

template <class T>
std::set<T> set_intersection(const std::set<T>& a, const std::set<T>& b)
{
    std::set<T> result;
    std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(result, result.end()));
    return result;
}

template <class T>
std::set<T> set_difference(const std::set<T>& a, const std::set<T>& b)
{
    std::set<T> result;
    std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::inserter(result, result.end()));
    return result;
}

template <class T>
bool is_subset(const std::set<T>& set, const std::set<T>& subset)
{
    return std::includes(set.begin(), set.end(), subset.begin(), subset.end());
}

int main()
{
    using namespace set_display;
    std::set<int> a{2, 5, 7, 5, 9, 2}; //C++11 initialization syntax
    std::set<int> b{1, 5, 9, 7, 4 };
    std::cout << "a = " << a << '\n';
    std::cout << "b = " << b << '\n';

    int value1 = 8, value2 = 5;
    std::cout << "Set a " << (contains(a, value1) ? "contains " : "does not contain ") << value1 << '\n';
    std::cout << "Set a " << (contains(a, value2) ? "contains " : "does not contain ") << value2 << '\n';

    std::cout << "Union of a and b: " << set_union(a, b) << '\n';
    std::cout << "Intersection of a and b: " << set_intersection(a, b) << '\n';
    std::cout << "Difference of a and b: " << set_difference(a, b) << '\n';

    std::set<int> sub{5, 9};
    std::cout << "Set b " << (is_subset(a, b) ? "is" : "is not") << " a subset of a\n";
    std::cout << "Set " << sub << ' ' << (is_subset(a, sub) ? "is" : "is not") << " a subset of a\n";

    std::set<int> copy = a;
    std::cout << "a " << (a == copy ? "equals " : "does not equal ") << copy << '\n';

    return 0;
}

demonstrate various set operations including set creation, testing for an element in a set, performing union, intersection, and difference operations between two sets, checking for subset and equality between two sets. The code also optionally shows other set operations and methods to modify a mutable set. The set implementation could be done using an associative array, a binary search tree, a hash table, or an ordered array of binary bits. The code also makes use of the C++ standard library's set class and unordered_set.


#include <chrono>
#include <ranges>
#include <iostream>

int main() {
    std::cout << "Yuletide holidays must be allowed in the following years:\n";
    for (int year : std::views::iota(2008, 2121)
               | std::views::filter([](auto year) {
                    if (std::chrono::weekday{
                            std::chrono::year{year}/std::chrono::December/25}
                            == std::chrono::Sunday) {
                        return true;
                    }
                    return false;
                })) {
        std::cout << year << '\n';
    }
}

The code determines the years between 2008 and 2121 where Christmas (25th December) falls on a Sunday, using standard date handling libraries. It also compares the results with other languages to identify any anomalies in date/time representation, such as overflow issues similar to y2k problems.