RosettaCodeData/Task/Include-a-file/AArch64-Assembly/include-a-file.aarch64
2023-07-01 13:44:08 -04:00

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"