Task

Write a program which uses a timer (with the least granularity available
on your system) to time how long a function takes to execute.

Whenever possible, use methods which measure only the processing time used
by the current process; instead of the difference in system time
between start and finish, which could include time used by
other processes on the computer.

This task is intended as a subtask for Measure relative performance of sorting algorithms implementations.




 
/* ARM assembly Raspberry PI  */
/*  program fcttime.s   */
 
/* Constantes    */
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
 
.equ N1, 1000000   @ loop number
.equ NBMEASURE, 10 @ measure number
 
/*********************************/
/* Initialized data              */
/*********************************/
.data
szMessError:       .asciz "Error detected !!!!. \n"
szMessSep:         .asciz "****************************\n"
szMessTemps:       .ascii "Function time : "
sSecondes:         .fill 10,1,' '
                   .ascii " s "
sMicroS:           .fill 10,1,' '
                   .asciz " micros\n"
 
szCarriageReturn:  .asciz "\n"
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss 
.align 4
dwDebut:           .skip 8
dwFin:             .skip 8
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                     @ entry of program 
    adr r0,mult                           @ function address to measure
    mov r1,#1                             @ parameter 1 function
    mov r2,#2                             @ parameter 2 function
    bl timeMesure
    cmp r0,#0
    blt 99f
    adr r0,sum                            @ function address to measure
    mov r1,#1
    mov r2,#2
    bl timeMesure
    cmp r0,#0
    blt 99f
    b 100f
99:
    @ error
    ldr r0,iAdrszMessError
    bl affichageMess       
100:                                       @ standard end of the program 
    mov r0, #0                             @ return code
    mov r7, #EXIT                          @ request to exit program
    svc #0                                 @ perform the system call
 
iAdrszMessError:          .int szMessError
iAdrszCarriageReturn:     .int szCarriageReturn
/**************************************************************/
/*   examble function sum                                     */
/**************************************************************/
/* r0 contains op 1     */
/* r1 contains op 2     */
sum:
    push {lr}                  @ save registres
    add r0,r1
100:
    pop {lr}                   @ restaur registers
    bx lr                      @ function return
 
/**************************************************************/
/*   exemple execution multiplication                         */
/**************************************************************/
/* r0 contains op 1     */
/* r1 contains op 2     */
mult:
    push {lr}                  @ save registres
    mul r0,r1,r0
100:
    pop {lr}                   @ restaur registers
    bx lr                      @ function return
 
/**************************************************************/
/*   Procedure for measuring the execution time of a routine  */
/**************************************************************/
/* r0 contains the function address     */
timeMesure:
    push {r1-r8,lr}                      @ save registres
    mov r4,r0                            @ save function address
    mov r5,r1                            @ save param 1
    mov r6,r2                            @ save param 2
    mov r8,#0
1:
    ldr r0,iAdrdwDebut                   @ start time area
    mov r1,#0
    mov r7, #0x4e                        @ call system gettimeofday
    svc #0 
    cmp r0,#0                            @ error ?
    blt 100f                             @ return error
    ldr r7,iMax                          @ run number
    mov r0,r5                            @ param function 1
    mov r1,r6                            @ param function 2
2:                                       @ loop
    blx r4                               @ call of the function to be measured
    subs r7,#1                           @ decrement run
    bge 2b                               @ loop if not zero
    @
    ldr r0,iAdrdwFin                     @ end time area
    mov r1,#0
    mov r7, #0x4e                        @ call system gettimeofday
    svc #0 
    cmp r0,#0                            @ error ?
    blt 100f                             @ return error
                                         @ compute time
    ldr r0,iAdrdwDebut                   @ start time area
    //vidmemtit mesure r0 2
    ldr r2,[r0]                          @ secondes
    ldr r3,[r0,#4]                       @ micro secondes
    ldr r0,iAdrdwFin                     @ end time area
    ldr r1,[r0]                          @ secondes
    ldr r0,[r0,#4]                       @ micro secondes
    sub r2,r1,r2                         @ secondes number
    subs r3,r0,r3                        @ microsecondes number
    sublt r2,#1                          @ if negative sub 1 seconde to secondes
    ldr r1,iSecMicro
    addlt r3,r1                          @ and add 1000000 to microsecondes number
    mov r0,r2                            @ conversion secondes 
    ldr r1,iAdrsSecondes
    bl conversion10
    mov r0,r3                            @ conversion microsecondes
    ldr r1,iAdrsMicroS
    bl conversion10
    ldr r0,iAdrszMessTemps
    bl affichageMess                     @ display message
    add r8,#1
    cmp r8,#NBMEASURE
    ble 1b
    ldr r0,iAdrszMessSep                 @ display separator
    bl affichageMess   
100:
    pop {r1-r8,lr}                       @ restaur registers
    bx lr                                @ function return
iMax:                 .int N1 
iAdrdwDebut:          .int dwDebut
iAdrdwFin:            .int dwFin
iSecMicro:            .int 1000000
iAdrsSecondes:        .int sSecondes
iAdrsMicroS:          .int sMicroS
iAdrszMessTemps:      .int szMessTemps
iAdrszMessSep:        .int szMessSep
 
/******************************************************************/
/*     display text with size calculation                         */ 
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                   @ save  registres
    mov r2,#0                               @ counter length 
1:                                          @ loop length calculation 
    ldrb r1,[r0,r2]                         @ read octet start position + index 
    cmp r1,#0                               @ if 0 its over 
    addne r2,r2,#1                          @ else add 1 in the length 
    bne 1b                                  @ and loop 
                                            @ so here r2 contains the length of the message 
    mov r1,r0                               @ address message in r1 
    mov r0,#STDOUT                          @ code to write to the standard output Linux 
    mov r7, #WRITE                          @ code call system "write" 
    svc #0                                  @ call systeme 
    pop {r0,r1,r2,r7,lr}                    @ restaur registers */ 
    bx lr                                   @ return  
/******************************************************************/
/*     Converting a register to a decimal                                 */ 
/******************************************************************/
/* r0 contains value and r1 address area   */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                         @ save registers 
    mov r3,r1
    mov r2,#LGZONECAL
1:                                          @ start loop
    bl divisionpar10                        @ r0 <- dividende. quotient ->r0 reste -> r1
    add r1,#48                              @ digit
    strb r1,[r3,r2]                         @ store digit on area
    cmp r0,#0                               @ stop if quotient = 0 
    subne r2,#1                               @ previous position    
    bne 1b                                  @ else loop
                                            @ end replaces digit in front of area
    mov r4,#0
2:
    ldrb r1,[r3,r2] 
    strb r1,[r3,r4]                         @ store in area begin
    add r4,#1
    add r2,#1                               @ previous position
    cmp r2,#LGZONECAL                       @ end
    ble 2b                                  @ loop
    mov r1,#' '
3:
    strb r1,[r3,r4]
    add r4,#1
    cmp r4,#LGZONECAL                       @ end
    ble 3b
100:
    pop {r1-r4,lr}                          @ restaur registres 
    bx lr                                   @return
/***************************************************/
/*   division par 10   signé                       */
/* Thanks to http://thinkingeek.com/arm-assembler-raspberry-pi/*  
/* and   http://www.hackersdelight.org/            */
/***************************************************/
/* r0 dividende   */
/* r0 quotient */
/* r1 remainder  */
divisionpar10:
  /* r0 contains the argument to be divided by 10 */
    push {r2-r4}                           @ save registers  */
    mov r4,r0  
    mov r3,#0x6667                         @ r3 <- magic_number  lower
    movt r3,#0x6666                        @ r3 <- magic_number  upper
    smull r1, r2, r3, r0                   @ r1 <- Lower32Bits(r1*r0). r2 <- Upper32Bits(r1*r0) 
    mov r2, r2, ASR #2                     @ r2 <- r2 >> 2
    mov r1, r0, LSR #31                    @ r1 <- r0 >> 31
    add r0, r2, r1                         @ r0 <- r2 + r1 
    add r2,r0,r0, lsl #2                   @ r2 <- r0 * 5 
    sub r1,r4,r2, lsl #1                   @ r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10)
    pop {r2-r4}
    bx lr                                  @ return
 