426 lines
18 KiB
Text
426 lines
18 KiB
Text
'file constant include : includeConstantesARM64.inc'
|
|
/*******************************************/
|
|
/* Constantes */
|
|
/*******************************************/
|
|
.equ STDIN, 0 // Linux input console
|
|
.equ STDOUT, 1 // linux output console
|
|
.equ OPEN, 56 // call system Linux 64 bits
|
|
.equ CLOSE, 57 // call system Linux 64 bits
|
|
.equ READ, 63 // call system Linux 64 bits
|
|
.equ WRITE, 64 // call system Linux 64 bits
|
|
.equ EXIT, 93 // call system Linux 64 bits
|
|
.equ HEAPSIZE, 100000
|
|
.equ CHARPOS, '@' // position character
|
|
|
|
/* file */
|
|
.equ O_RDONLY, 0
|
|
.equ O_WRONLY, 0x0001
|
|
.equ O_RDWR, 0x0002 // open for reading and writing
|
|
|
|
.equ O_CREAT, 0x040 // create if nonexistant
|
|
.equ O_TRUNC, 0x0400 // truncate to zero length
|
|
.equ O_EXCL, 0x0800 // error if already exists
|
|
|
|
.equ AT_FDCWD, -100
|
|
'file fonctions include : includeARM64.inc'
|
|
/* File include fonctions */
|
|
.data
|
|
ptzZoneHeap: .quad zZoneHeap
|
|
.bss
|
|
.align 8
|
|
zZoneHeap: .skip HEAPSIZE
|
|
zEndZoneHeap:
|
|
.text
|
|
/******************************************************************/
|
|
/* String display with size compute */
|
|
/******************************************************************/
|
|
/* x0 contains string address (string ended with zero binary) */
|
|
affichageMess:
|
|
stp x0,x1,[sp,-16]! // save registers
|
|
stp x2,x8,[sp,-16]! // save registers
|
|
mov x2,0 // size counter
|
|
1: // loop start
|
|
ldrb w1,[x0,x2] // load a byte
|
|
cbz w1,2f // if zero -> end string
|
|
add x2,x2,#1 // else increment counter
|
|
b 1b // and loop
|
|
2: // x2 = string size
|
|
mov x1,x0 // string address
|
|
mov x0,STDOUT // output Linux standard
|
|
mov x8,WRITE // code call system "write"
|
|
svc 0 // call systeme Linux
|
|
ldp x2,x8,[sp],16 // restaur 2 registres
|
|
ldp x0,x1,[sp],16 // restaur 2 registres
|
|
ret // retour adresse lr x30
|
|
/******************************************************************/
|
|
/* Decimal conversion unsigned */
|
|
/******************************************************************/
|
|
/* x0 contains the value */
|
|
/* x1 contains the address of receiving area length >= 21 */
|
|
/* the receiving area return a string ascii left aligned */
|
|
/* and with final zero */
|
|
/* x0 return length string whitout zero final */
|
|
.equ LGZONECONV, 20
|
|
conversion10:
|
|
stp x5,lr,[sp,-16]! // save registers
|
|
stp x3,x4,[sp,-16]! // save registers
|
|
stp x1,x2,[sp,-16]! // save registers
|
|
mov x4,#LGZONECONV // position last digit
|
|
mov x5,#10 // decimal conversion
|
|
1: // loop begin
|
|
mov x2,x0 // copy starting number or successive quotients
|
|
udiv x0,x2,x5 // division by ten
|
|
msub x3,x0,x5,x2 //compute remainder
|
|
add x3,x3,#48 // digit
|
|
sub x4,x4,#1 // previous position
|
|
strb w3,[x1,x4] // store digit ascii
|
|
cbnz x0,1b // end if quotient = zero
|
|
mov x2,LGZONECONV // compute string length (20 - dernière position)
|
|
sub x0,x2,x4 // no instruction rsb in 64 bits !!!
|
|
// move result to area begin
|
|
cbz x4,3f // full area ?
|
|
mov x2,0 // start position
|
|
2:
|
|
ldrb w3,[x1,x4] // load digit
|
|
strb w3,[x1,x2] // store digit
|
|
add x4,x4,#1 // next position origin
|
|
add x2,x2,#1 // and next position destination
|
|
cmp x4,LGZONECONV - 1 // end ?
|
|
ble 2b // else loop
|
|
3:
|
|
mov w3,0
|
|
strb w3,[x1,x2] // zero final
|
|
100:
|
|
ldp x1,x2,[sp],16 // restaur des 2 registres
|
|
ldp x3,x4,[sp],16 // restaur des 2 registres
|
|
ldp x5,lr,[sp],16 // restaur des 2 registres
|
|
ret // retour adresse lr x30
|
|
/******************************************************************/
|
|
/* Decimal conversion signed */
|
|
/******************************************************************/
|
|
/* x0 contains the value */
|
|
/* x1 contains the address of receiving area length >= 21 */
|
|
/* the receiving area return a string ascii left aligned */
|
|
/* et avec un zero final */
|
|
/* x0 return length string whitout zero final */
|
|
.equ LGZONECONVS, 21
|
|
conversion10S:
|
|
stp x5,lr,[sp,-16]! // save registers
|
|
stp x3,x4,[sp,-16]! // save registers
|
|
stp x1,x2,[sp,-16]! // save registers
|
|
cmp x0,0 // is negative ?
|
|
bge 11f // no
|
|
mov x3,'-' // yes
|
|
neg x0,x0 // number inversion
|
|
b 12f
|
|
11:
|
|
mov x3,'+' // positive number
|
|
12:
|
|
strb w3,[x1]
|
|
mov x4,#LGZONECONVS // position last digit
|
|
mov x5,#10 // decimal conversion
|
|
1: // loop conversion start
|
|
mov x2,x0 // copy starting number or successive quotients
|
|
udiv x0,x2,x5 // division by ten
|
|
msub x3,x0,x5,x2 //compute remainder
|
|
add x3,x3,#48 // conversion ascii
|
|
sub x4,x4,#1 // previous position
|
|
strb w3,[x1,x4] // store digit
|
|
cbnz x0,1b // end if quotient = zero
|
|
|
|
mov x2,LGZONECONVS // compute string length (21 - dernière position)
|
|
sub x0,x2,x4 // no instruction rsb in 64 bits !!!
|
|
// move result to area begin
|
|
cmp x4,1
|
|
beq 3f // full area ?
|
|
mov x2,1 // no -> begin area
|
|
2:
|
|
ldrb w3,[x1,x4] // load a digit
|
|
strb w3,[x1,x2] // and store at begin area
|
|
add x4,x4,#1 // last position
|
|
add x2,x2,#1 // et begin last postion
|
|
cmp x4,LGZONECONVS - 1 // end ?
|
|
ble 2b // no -> loop
|
|
3:
|
|
mov w3,0
|
|
strb w3,[x1,x2] // zero final
|
|
add x0,x0,1 // string length must take into account the sign
|
|
100:
|
|
ldp x1,x2,[sp],16 // restaur 2 registers
|
|
ldp x3,x4,[sp],16 // restaur 2 registers
|
|
ldp x5,lr,[sp],16 // restaur 2 registers
|
|
ret // return address lr x30
|
|
/******************************************************************/
|
|
/* conversion hexadecimal register */
|
|
/******************************************************************/
|
|
/* x0 contains value and x1 address zone receptrice */
|
|
conversion16:
|
|
stp x0,lr,[sp,-48]! // save registres
|
|
stp x1,x2,[sp,32] // save registres
|
|
stp x3,x4,[sp,16] // save registres
|
|
mov x2,#60 // start bit position
|
|
mov x4,#0xF000000000000000 // mask
|
|
mov x3,x0 // save entry value
|
|
1: // start loop
|
|
and x0,x3,x4 // value register and mask
|
|
lsr x0,x0,x2 // right shift
|
|
cmp x0,#10 // >= 10 ?
|
|
bge 2f // yes
|
|
add x0,x0,#48 // no is digit
|
|
b 3f
|
|
2:
|
|
add x0,x0,#55 // else is a letter A-F
|
|
3:
|
|
strb w0,[x1],#1 // load result and + 1 in address
|
|
lsr x4,x4,#4 // shift mask 4 bits left
|
|
subs x2,x2,#4 // decrement counter 4 bits <= zero ?
|
|
bge 1b // no -> loop
|
|
|
|
100: // fin standard de la fonction
|
|
ldp x3,x4,[sp,16] // restaur des 2 registres
|
|
ldp x1,x2,[sp,32] // restaur des 2 registres
|
|
ldp x0,lr,[sp],48 // restaur des 2 registres
|
|
ret
|
|
/******************************************************************/
|
|
/* conversion ascii string to number */
|
|
/******************************************************************/
|
|
/* x0 contains string address ended by 0x0 or 0xA */
|
|
/* x0 return the number */
|
|
conversionAtoD:
|
|
stp x5,lr,[sp,-16]! // save registers
|
|
stp x3,x4,[sp,-16]! // save registers
|
|
stp x1,x2,[sp,-16]! // save registers
|
|
mov x1,#0
|
|
mov x2,#10 // factor ten
|
|
mov x4,x0 // save address in x4
|
|
mov x3,#0 // positive signe by default
|
|
mov x0,#0 // init résult to zéro
|
|
mov x5,#0
|
|
1: // loop to remove space at begin of string
|
|
ldrb w5,[x4],1 // load in w5 string octet
|
|
cbz w5,100f // string end -> end routine
|
|
cmp w5,#0x0A // string end -> end routine
|
|
beq 100f
|
|
cmp w5,#' ' // space ?
|
|
beq 1b // yes -> loop
|
|
2:
|
|
cmp x5,#'-' // first character is -
|
|
bne 3f
|
|
mov x3,#1 // negative number
|
|
b 4f // previous position
|
|
3: // begin loop compute digit
|
|
cmp x5,#'0' // character not a digit
|
|
blt 4f
|
|
cmp x5,#'9' // character not a digit
|
|
bgt 4f
|
|
// character is a digit
|
|
sub w5,w5,#48
|
|
|
|
mul x0,x2,x0 // multiply last result by factor
|
|
smulh x1,x2,x0 // hight
|
|
cbnz x1,99f // overflow ?
|
|
add x0,x0,x5 // no -> add to result
|
|
4:
|
|
ldrb w5,[x4],1 // load new octet and increment to one
|
|
cbz w5,5f // string end -> end routine
|
|
cmp w5,#0xA // string end ?
|
|
bne 3b // no -> loop
|
|
5:
|
|
cmp x3,#1 // test register x3 for signe
|
|
cneg x0,x0,eq // if equal egal negate value
|
|
cmn x0,0 // carry to zero no error
|
|
b 100f
|
|
99: // overflow
|
|
adr x0,szMessErrDep
|
|
bl affichageMess
|
|
cmp x0,0 // carry to one error
|
|
mov x0,#0 // if error return zéro
|
|
100:
|
|
ldp x1,x2,[sp],16 // restaur 2 registers
|
|
ldp x3,x4,[sp],16 // restaur 2 registers
|
|
ldp x5,lr,[sp],16 // restaur 2 registers
|
|
ret // retur address lr x30
|
|
szMessErrDep: .asciz "Number too large: overflow of 64 bits. :\n"
|
|
.align 4 // instruction to realign the following routines
|
|
/***************************************************/
|
|
/* reserve heap area */
|
|
/***************************************************/
|
|
// x0 contains size in byte to reserve */
|
|
// x0 returne begin address of area */
|
|
reserverPlace: // INFO: reserverPlace
|
|
stp x1,lr,[sp,-16]! // save registers
|
|
stp x2,x3,[sp,-16]! // save registers
|
|
mov x1,x0
|
|
tst x1,#0b111 // size multiple of 8 ?
|
|
beq 1f // yes
|
|
and x1,x1,0xFFFFFFFFFFFFFFF8 // else align to 8 superior
|
|
add x1,x1,8
|
|
1:
|
|
ldr x2,qAdrptzZoneHeap
|
|
ldr x0,[x2]
|
|
add x1,x1,x0 // size too large ?
|
|
ldr x3,qAdrzEndZoneHeap
|
|
cmp x1,x3
|
|
blt 2f // no it is ok
|
|
adr x0,szMessErrTas // yes -> error
|
|
bl affichageMess
|
|
mov x0,#-1
|
|
b 100f
|
|
2:
|
|
str x1,[x2] // store new pointer
|
|
100: // fin standard de la fonction
|
|
ldp x2,x3,[sp],16 // restaur 2 registers
|
|
ldp x1,lr,[sp],16 // restaur 2 registers
|
|
ret // retur address lr x30
|
|
qAdrptzZoneHeap: .quad ptzZoneHeap
|
|
qAdrzEndZoneHeap: .quad zEndZoneHeap
|
|
szMessErrTas: .asciz "Error : heap not large !!!\n"
|
|
.align 4
|
|
/***************************************************/
|
|
/* liberer place sur le tas */
|
|
/***************************************************/
|
|
// r0 contains begin address area
|
|
libererPlace: // INFO: libererPlace
|
|
stp x1,lr,[sp,-16]! // save registers
|
|
ldr x1,qAdrzZoneHeap
|
|
cmp x0,x1
|
|
blt 99f
|
|
ldr x1,qAdrzEndZoneHeap
|
|
cmp x0,x1
|
|
bge 99f
|
|
ldr x1,qAdrptzZoneHeap
|
|
str x0,[x1]
|
|
b 100f
|
|
99:
|
|
adr x0,szMessErrTas1
|
|
bl affichageMess
|
|
mov x0,-1
|
|
100:
|
|
ldp x1,lr,[sp],16 // restaur 2 registers
|
|
ret // retur address lr x30
|
|
qAdrzZoneHeap: .quad zZoneHeap
|
|
szMessErrTas1: .asciz "Error : address < or > heap addresses !!!\n"
|
|
.align 4
|
|
|
|
/******************************************************************/
|
|
/* insert string at character insertion */
|
|
/******************************************************************/
|
|
/* x0 contains the address of string 1 */
|
|
/* x1 contains the address of insertion string */
|
|
/* x0 return the address of new string on the heap */
|
|
/* or -1 if error */
|
|
strInsertAtCharInc:
|
|
stp x2,lr,[sp,-16]! // save registers
|
|
stp x3,x4,[sp,-16]! // save registers
|
|
stp x5,x6,[sp,-16]! // save registers
|
|
stp x7,x8,[sp,-16]! // save registers
|
|
mov x3,#0 // length counter
|
|
1: // compute length of string 1
|
|
ldrb w4,[x0,x3]
|
|
cmp w4,#0
|
|
cinc x3,x3,ne // increment to one if not equal
|
|
bne 1b // loop if not equal
|
|
mov x5,#0 // length counter insertion string
|
|
2: // compute length to insertion string
|
|
ldrb w4,[x1,x5]
|
|
cmp x4,#0
|
|
cinc x5,x5,ne // increment to one if not equal
|
|
bne 2b // and loop
|
|
cmp x5,#0
|
|
beq 99f // string empty -> error
|
|
add x3,x3,x5 // add 2 length
|
|
add x3,x3,#1 // +1 for final zero
|
|
mov x6,x0 // save address string 1
|
|
mov x0,x3
|
|
bl reserverPlace
|
|
cmp x0,#-1 // allocation error
|
|
beq 99f
|
|
mov x5,x0 // save address heap for output string
|
|
mov x2,0
|
|
mov x4,0
|
|
3: // loop copy string begin
|
|
ldrb w3,[x6,x2]
|
|
cmp w3,0
|
|
beq 99f
|
|
cmp w3,CHARPOS // insertion character ?
|
|
beq 5f // yes
|
|
strb w3,[x5,x4] // no store character in output string
|
|
add x2,x2,1
|
|
add x4,x4,1
|
|
b 3b // and loop
|
|
5: // x4 contains position insertion
|
|
add x8,x4,1 // init index character output string
|
|
// at position insertion + one
|
|
mov x3,#0 // index load characters insertion string
|
|
6:
|
|
ldrb w0,[x1,x3] // load characters insertion string
|
|
cmp w0,#0 // end string ?
|
|
beq 7f // yes
|
|
strb w0,[x5,x4] // store in output string
|
|
add x3,x3,#1 // increment index
|
|
add x4,x4,#1 // increment output index
|
|
b 6b // and loop
|
|
7: // loop copy end string
|
|
ldrb w0,[x6,x8] // load other character string 1
|
|
strb w0,[x5,x4] // store in output string
|
|
cmp x0,#0 // end string 1 ?
|
|
beq 8f // yes -> end
|
|
add x4,x4,#1 // increment output index
|
|
add x8,x8,#1 // increment index
|
|
b 7b // and loop
|
|
8:
|
|
mov x0,x5 // return output string address
|
|
b 100f
|
|
99: // error
|
|
mov x0,#-1
|
|
100:
|
|
ldp x7,x8,[sp],16 // restaur 2 registers
|
|
ldp x5,x6,[sp],16 // restaur 2 registers
|
|
ldp x3,x4,[sp],16 // restaur 2 registers
|
|
ldp x2,lr,[sp],16 // restaur 2 registers
|
|
ret
|
|
|
|
'Main program '
|
|
/* ARM assembly AARCH64 Raspberry PI 3B */
|
|
/* program include.s */
|
|
|
|
/*******************************************/
|
|
/* Constantes file */
|
|
/*******************************************/
|
|
.include "../includeConstantesARM64.inc"
|
|
|
|
/*******************************************/
|
|
/* Initialized data */
|
|
/*******************************************/
|
|
.data
|
|
szMessResult: .asciz "Number = "
|
|
szRetourLigne: .asciz "\n"
|
|
/*******************************************/
|
|
/* Uninitialized data */
|
|
/*******************************************/
|
|
.bss
|
|
sZoneConv: .skip 100
|
|
.text
|
|
.global main
|
|
main:
|
|
|
|
mov x0,1000 // number
|
|
ldr x1,qAdrsZoneConv
|
|
bl conversion10S // result decimal conversion
|
|
ldr x0,qAdrszMessResult
|
|
bl affichageMess // call function display
|
|
ldr x0,qAdrsZoneConv
|
|
bl affichageMess // call function display
|
|
ldr x0, qAdrszRetourLigne
|
|
bl affichageMess
|
|
mov x0,0 // return code OK
|
|
100: // standard end programm
|
|
mov x8,EXIT // request to exit program
|
|
svc 0 // perform the system call
|
|
qAdrszMessResult: .quad szMessResult
|
|
qAdrsZoneConv: .quad sZoneConv
|
|
qAdrszRetourLigne: .quad szRetourLigne
|
|
/********************************************************/
|
|
/* File Include fonctions */
|
|
/********************************************************/
|
|
.include "../includeARM64.inc"
|