RosettaCodeData/Task/AVL-tree/ARM-Assembly/avl-tree.arm

765 lines
25 KiB
Plaintext

/* ARM assembly Raspberry PI */
/* program avltree2.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 */
/*******************************************/
/* Constantes */
/*******************************************/
.equ STDOUT, 1 @ Linux output console
.equ EXIT, 1 @ Linux syscall
.equ WRITE, 4 @ Linux syscall
.equ BRK, 0x2d @ Linux syscall
.equ CHARPOS, '@'
.equ NBVAL, 12
/*******************************************/
/* Structures */
/********************************************/
/* structure tree */
.struct 0
tree_root: @ root pointer (or node right)
.struct tree_root + 4
tree_size: @ number of element of tree
.struct tree_size + 4
tree_suite:
.struct tree_suite + 12 @ for alignement to node
tree_fin:
/* structure node tree */
.struct 0
node_right: @ right pointer
.struct node_right + 4
node_left: @ left pointer
.struct node_left + 4
node_value: @ element value
.struct node_value + 4
node_height: @ element value
.struct node_height + 4
node_parent: @ element value
.struct node_parent + 4
node_fin:
/* structure queue*/
.struct 0
queue_begin: @ next pointer
.struct queue_begin + 4
queue_end: @ element value
.struct queue_end + 4
queue_fin:
/* structure node queue */
.struct 0
queue_node_next: @ next pointer
.struct queue_node_next + 4
queue_node_value: @ element value
.struct queue_node_value + 4
queue_node_fin:
/*******************************************/
/* Initialized data */
/*******************************************/
.data
szMessPreOrder: .asciz "PreOrder :\n"
szCarriageReturn: .asciz "\n"
/* datas error display */
szMessErreur: .asciz "Error detected.\n"
szMessKeyDbl: .asciz "Key exists in tree.\n"
szMessInsInv: .asciz "Insertion in inverse order.\n"
/* datas message display */
szMessResult: .asciz "Ele: @ G: @ D: @ val @ h @ pere @\n"
sValue: .space 12,' '
.asciz "\n"
/*******************************************/
/* UnInitialized data */
/*******************************************/
.bss
sZoneConv: .skip 24
stTree: .skip tree_fin @ place to structure tree
stTree1: .skip tree_fin @ place to structure tree
stQueue: .skip queue_fin @ place to structure queue
/*******************************************/
/* code section */
/*******************************************/
.text
.global main
main:
mov r8,#1 @ node tree value
1: @ loop insertion in order
ldr r0,iAdrstTree @ structure tree address
mov r1,r8
bl insertElement @ add element value r1
cmp r0,#-1
beq 99f
//ldr r3,iAdrstTree @ tree root address (begin structure)
//ldr r0,[r3,#tree_root]
//ldr r1,iAdrdisplayElement @ function to execute
//bl preOrder
add r8,#1 @ increment value
cmp r8,#NBVAL @ end ?
ble 1b @ no -> loop
ldr r0,iAdrstTree @ structure tree address
mov r1,#11 @ verif key dobble
bl insertElement @ add element value r1
cmp r0,#-1
bne 2f
ldr r0,iAdrszMessErreur
bl affichageMess
2:
ldr r0,iAdrszMessPreOrder @ load verification
bl affichageMess
ldr r3,iAdrstTree @ tree root address (begin structure)
ldr r0,[r3,#tree_root]
ldr r1,iAdrdisplayElement @ function to execute
bl preOrder
ldr r0,iAdrszMessInsInv
bl affichageMess
mov r8,#NBVAL @ node tree value
3: @ loop insertion inverse order
ldr r0,iAdrstTree1 @ structure tree address
mov r1,r8
bl insertElement @ add element value r1
cmp r0,#-1
beq 99f
sub r8,#1 @ increment value
cmp r8,#0 @ end ?
bgt 3b @ no -> loop
ldr r0,iAdrszMessPreOrder @ load verification
bl affichageMess
ldr r3,iAdrstTree1 @ tree root address (begin structure)
ldr r0,[r3,#tree_root]
ldr r1,iAdrdisplayElement @ function to execute
bl preOrder
@ search value
ldr r0,iAdrstTree1 @ tree root address (begin structure)
mov r1,#11 @ value to search
bl searchTree
cmp r0,#-1
beq 100f
mov r2,r0
ldr r0,iAdrszMessKeyDbl @ key exists
bl affichageMess
@ suppresssion previous value
mov r0,r2
ldr r1,iAdrstTree1
bl supprimer
ldr r0,iAdrszMessPreOrder @ verification
bl affichageMess
ldr r3,iAdrstTree1 @ tree root address (begin structure)
ldr r0,[r3,#tree_root]
ldr r1,iAdrdisplayElement @ function to execute
bl preOrder
b 100f
99: @ display error
ldr r0,iAdrszMessErreur
bl affichageMess
100: @ standard end of the program
mov r7, #EXIT @ request to exit program
svc 0 @ perform system call
iAdrszMessPreOrder: .int szMessPreOrder
iAdrszMessErreur: .int szMessErreur
iAdrszCarriageReturn: .int szCarriageReturn
iAdrstTree: .int stTree
iAdrstTree1: .int stTree1
iAdrstQueue: .int stQueue
iAdrdisplayElement: .int displayElement
iAdrszMessInsInv: .int szMessInsInv
/******************************************************************/
/* insert element in the tree */
/******************************************************************/
/* r0 contains the address of the tree structure */
/* r1 contains the value of element */
/* r0 returns address of element or - 1 if error */
insertElement: @ INFO: insertElement
push {r1-r8,lr} @ save registers
mov r7,r0 @ save head
mov r0,#node_fin @ reservation place one element
bl allocHeap
cmp r0,#-1 @ allocation error
beq 100f
mov r5,r0
str r1,[r5,#node_value] @ store value in address heap
mov r3,#0
str r3,[r5,#node_left] @ init left pointer with zero
str r3,[r5,#node_right] @ init right pointer with zero
str r3,[r5,#node_height] @ init balance with zero
ldr r2,[r7,#tree_size] @ load tree size
cmp r2,#0 @ 0 element ?
bne 1f
str r5,[r7,#tree_root] @ yes -> store in root
b 4f
1: @ else search free address in tree
ldr r3,[r7,#tree_root] @ start with address root
2: @ begin loop to insertion
ldr r4,[r3,#node_value] @ load key
cmp r1,r4
beq 6f @ key equal
blt 3f @ key <
@ key > insertion right
ldr r8,[r3,#node_right] @ node empty ?
cmp r8,#0
movne r3,r8 @ no -> next node
bne 2b @ and loop
str r5,[r3,#node_right] @ store node address in right pointer
b 4f
3: @ left
ldr r8,[r3,#node_left] @ left pointer empty ?
cmp r8,#0
movne r3,r8 @
bne 2b @ no -> loop
str r5,[r3,#node_left] @ store node address in left pointer
4:
str r3,[r5,#node_parent] @ store parent
mov r4,#1
str r4,[r5,#node_height] @ store height = 1
mov r0,r5 @ begin node to requilbrate
mov r1,r7 @ head address
bl equilibrer
5:
add r2,#1 @ increment tree size
str r2,[r7,#tree_size]
mov r0,#0
b 100f
6: @ key equal ?
ldr r0,iAdrszMessKeyDbl
bl affichageMess
mov r0,#-1
b 100f
100:
pop {r1-r8,lr} @ restaur registers
bx lr @ return
iAdrszMessKeyDbl: .int szMessKeyDbl
/******************************************************************/
/* equilibrer after insertion */
/******************************************************************/
/* r0 contains the address of the node */
/* r1 contains the address of head */
equilibrer: @ INFO: equilibrer
push {r1-r8,lr} @ save registers
mov r3,#0 @ balance factor
1: @ begin loop
ldr r5,[r0,#node_parent] @ load father
cmp r5,#0 @ end ?
beq 5f
cmp r3,#2 @ right tree too long
beq 5f
cmp r3,#-2 @ left tree too long
beq 5f
mov r6,r0 @ s = current
ldr r0,[r6,#node_parent] @ current = father
ldr r7,[r0,#node_left]
cmp r7,#0
ldrne r8,[r7,#node_height] @ height left tree
moveq r8,#0
ldr r7,[r0,#node_right]
cmp r7,#0
ldrne r9,[r7,#node_height] @ height right tree
moveq r9,#0
cmp r8,r9
addgt r8,#1
strgt r8,[r0,#node_height]
addle r9,#1
strle r9,[r0,#node_height]
//
ldr r7,[r0,#node_right]
cmp r7,#0
ldrne r8,[r7,#node_height]
moveq r8,#0
ldr r7,[r0,#node_left]
cmp r7,#0
ldrne r9,[r7,#node_height]
moveq r9,#0
sub r3,r8,r9 @ compute balance factor
b 1b
5:
cmp r3,#2
beq 6f
cmp r3,#-2
beq 6f
b 100f
6:
mov r3,r1
mov r4,r0
mov r1,r6
bl equiUnSommet
@ change head address ?
ldr r2,[r3,#tree_root]
cmp r2,r4
streq r6,[r3,#tree_root]
100:
pop {r1-r8,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* equilibre 1 sommet */
/******************************************************************/
/* r0 contains the address of the node */
/* r1 contains the address of the node */
equiUnSommet: @ INFO: equiUnSommet
push {r1-r9,lr} @ save registers
mov r5,r0 @ save p
mov r6,r1 // s
ldr r2,[r5,#node_left]
cmp r2,r6
bne 5f
ldr r7,[r5,#node_right]
cmp r7,#0
moveq r8,#0
ldrne r8,[r7,#node_height]
ldr r7,[r5,#node_left]
cmp r7,#0
moveq r9,#0
ldrne r9,[r7,#node_height]
sub r3,r8,r9
cmp r3,#-2
bne 100f
ldr r7,[r6,#node_right]
cmp r7,#0
moveq r8,#0
ldrne r8,[r7,#node_height]
ldr r7,[r6,#node_left]
cmp r7,#0
moveq r9,#0
ldrne r9,[r7,#node_height]
sub r3,r8,r9
cmp r3,#1
bge 2f
mov r0,r5
bl rotRight
b 100f
2:
mov r0,r6
bl rotLeft
mov r0,r5
bl rotRight
b 100f
5:
ldr r7,[r5,#node_right]
cmp r7,#0
moveq r8,#0
ldrne r8,[r7,#node_height]
ldr r7,[r5,#node_left]
cmp r7,#0
moveq r9,#0
ldrne r9,[r7,#node_height]
sub r3,r8,r9
cmp r3,#2
bne 100f
ldr r7,[r6,#node_right]
cmp r7,#0
moveq r8,#0
ldrne r8,[r7,#node_height]
ldr r7,[r6,#node_left]
cmp r7,#0
moveq r9,#0
ldrne r9,[r7,#node_height]
sub r3,r8,r9
cmp r3,#-1
ble 2f
mov r0,r5
bl rotLeft
b 100f
2:
mov r0,r6
bl rotRight
mov r0,r5
bl rotLeft
b 100f
100:
pop {r1-r9,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* right rotation */
/******************************************************************/
/* r0 contains the address of the node */
rotRight: @ INFO: rotRight
push {r1-r5,lr} @ save registers
// r2 r2
// r0 r1
// r1 r0
// r3 r3
ldr r1,[r0,#node_left] @ load left children
ldr r2,[r0,#node_parent] @ load father
cmp r2,#0 @ no father ???
beq 2f
ldr r3,[r2,#node_left] @ load left node father
cmp r3,r0 @ equal current node ?
streq r1,[r2,#node_left] @ yes store left children
strne r1,[r2,#node_right] @ no store right
2:
str r2,[r1,#node_parent] @ change parent
str r1,[r0,#node_parent]
ldr r3,[r1,#node_right]
str r3,[r0,#node_left]
cmp r3,#0
strne r0,[r3,#node_parent] @ change parent node left
str r0,[r1,#node_right]
ldr r3,[r0,#node_left] @ compute newbalance factor
cmp r3,#0
moveq r4,#0
ldrne r4,[r3,#node_height]
ldr r3,[r0,#node_right]
cmp r3,#0
moveq r5,#0
ldrne r5,[r3,#node_height]
cmp r4,r5
addgt r4,#1
strgt r4,[r0,#node_height]
addle r5,#1
strle r5,[r0,#node_height]
//
ldr r3,[r1,#node_left] @ compute new balance factor
cmp r3,#0
moveq r4,#0
ldrne r4,[r3,#node_height]
ldr r3,[r1,#node_right]
cmp r3,#0
moveq r5,#0
ldrne r5,[r3,#node_height]
cmp r4,r5
addgt r4,#1
strgt r4,[r1,#node_height]
addle r5,#1
strle r5,[r1,#node_height]
100:
pop {r1-r5,lr} @ restaur registers
bx lr
/******************************************************************/
/* left rotation */
/******************************************************************/
/* r0 contains the address of the node sommet */
rotLeft: @ INFO: rotLeft
push {r1-r5,lr} @ save registers
// r2 r2
// r0 r1
// r1 r0
// r3 r3
ldr r1,[r0,#node_right] @ load right children
ldr r2,[r0,#node_parent] @ load father (racine)
cmp r2,#0 @ no father ???
beq 2f
ldr r3,[r2,#node_left] @ load left node father
cmp r3,r0 @ equal current node ?
streq r1,[r2,#node_left] @ yes store left children
strne r1,[r2,#node_right] @ no store to right
2:
str r2,[r1,#node_parent] @ change parent of right children
str r1,[r0,#node_parent] @ change parent of sommet
ldr r3,[r1,#node_left] @ left children
str r3,[r0,#node_right] @ left children pivot exists ?
cmp r3,#0
strne r0,[r3,#node_parent] @ yes store in
str r0,[r1,#node_left]
//
ldr r3,[r0,#node_left] @ compute new height for old summit
cmp r3,#0
moveq r4,#0
ldrne r4,[r3,#node_height] @ left height
ldr r3,[r0,#node_right]
cmp r3,#0
moveq r5,#0
ldrne r5,[r3,#node_height] @ right height
cmp r4,r5
addgt r4,#1
strgt r4,[r0,#node_height] @ if right > left
addle r5,#1
strle r5,[r0,#node_height] @ if left > right
//
ldr r3,[r1,#node_left] @ compute new height for new
cmp r3,#0
moveq r4,#0
ldrne r4,[r3,#node_height]
ldr r3,[r1,#node_right]
cmp r3,#0
moveq r5,#0
ldrne r5,[r3,#node_height]
cmp r4,r5
addgt r4,#1
strgt r4,[r1,#node_height]
addle r5,#1
strle r5,[r1,#node_height]
100:
pop {r1-r5,lr} @ restaur registers
bx lr
/******************************************************************/
/* search value in tree */
/******************************************************************/
/* r0 contains the address of structure of tree */
/* r1 contains the value to search */
searchTree: @ INFO: searchTree
push {r1-r4,lr} @ save registers
ldr r2,[r0,#tree_root]
1: @ begin loop
ldr r4,[r2,#node_value] @ load key
cmp r1,r4
beq 3f @ key equal
blt 2f @ key <
@ key > insertion right
ldr r3,[r2,#node_right] @ node empty ?
cmp r3,#0
movne r2,r3 @ no -> next node
bne 1b @ and loop
mov r0,#-1 @ not find
b 100f
2: @ left
ldr r3,[r2,#node_left] @ left pointer empty ?
cmp r3,#0
movne r2,r3 @
bne 1b @ no -> loop
mov r0,#-1 @ not find
b 100f
3:
mov r0,r2 @ return node address
100:
pop {r1-r4,lr} @ restaur registers
bx lr
/******************************************************************/
/* suppression node */
/******************************************************************/
/* r0 contains the address of the node */
/* r1 contains structure tree address */
supprimer: @ INFO: supprimer
push {r1-r8,lr} @ save registers
ldr r1,[r0,#node_left]
cmp r1,#0
bne 5f
ldr r1,[r0,#node_right]
cmp r1,#0
bne 5f
@ is a leaf
mov r4,#0
ldr r3,[r0,#node_parent] @ father
cmp r3,#0
streq r4,[r1,#tree_root]
beq 100f
ldr r1,[r3,#node_left]
cmp r1,r0
bne 2f
str r4,[r3,#node_left] @ suppression left children
ldr r5,[r3,#node_right]
cmp r5,#0
moveq r6,#0
ldrne r6,[r5,#node_height]
add r6,#1
str r6,[r3,#node_height]
b 3f
2: @ suppression right children
str r4,[r3,#node_right]
ldr r5,[r3,#node_left]
cmp r5,#0
moveq r6,#0
ldrne r6,[r5,#node_height]
add r6,#1
str r6,[r3,#node_height]
3: @ new balance
mov r0,r3
bl equilibrerSupp
b 100f
5: @ is not à leaf
ldr r7,[r0,#node_right]
cmp r7,#0
beq 7f
mov r8,r0
mov r0,r7
6:
ldr r6,[r0,#node_left]
cmp r6,#0
movne r0,r6
bne 6b
b 9f
7:
ldr r7,[r0,#node_left] @ search the litle element
cmp r7,#0
beq 9f
mov r8,r0
mov r0,r7
8:
ldr r6,[r0,#node_right] @ search the great element
cmp r6,#0
movne r0,r6
bne 8b
9:
ldr r5,[r0,#node_value] @ copy value
str r5,[r8,#node_value]
bl supprimer @ suppression node r0
100:
pop {r1-r8,lr} @ restaur registers
bx lr
/******************************************************************/
/* equilibrer after suppression */
/******************************************************************/
/* r0 contains the address of the node */
/* r1 contains the address of head */
equilibrerSupp: @ INFO: equilibrerSupp
push {r1-r8,lr} @ save registers
mov r3,#1 @ balance factor
ldr r2,[r1,#tree_root]
1:
ldr r5,[r0,#node_parent] @ load father
cmp r5,#0 @ no father
beq 100f
cmp r3,#0 @ balance equilibred
beq 100f
mov r6,r0 @ save entry node
ldr r0,[r6,#node_parent] @ current = father
ldr r7,[r0,#node_left]
cmp r7,#0
ldrne r8,[r7,#node_height] @ height left tree
moveq r8,#0
ldr r7,[r0,#node_right]
cmp r7,#0
ldrne r9,[r7,#node_height] @ height right tree
moveq r9,#0
cmp r8,r9
addgt r8,#1
strgt r8,[r0,#node_height]
addle r9,#1
strle r9,[r0,#node_height]
//
ldr r7,[r0,#node_right]
cmp r7,#0
ldrne r8,[r7,#node_height]
moveq r8,#0
ldr r7,[r0,#node_left]
cmp r7,#0
ldrne r9,[r7,#node_height]
moveq r9,#0
sub r3,r8,r9 @ compute balance factor
mov r2,r1
mov r4,r0 @ save current
mov r1,r6
bl equiUnSommet
@ change head address ?
cmp r2,r4
streq r6,[r3,#tree_root]
mov r0,r4 @ restaur current
b 1b
100:
pop {r1-r8,lr} @ restaur registers
bx lr @ return
/******************************************************************/
/* preOrder */
/******************************************************************/
/* r0 contains the address of the node */
/* r1 function address */
preOrder: @ INFO: preOrder
push {r1-r2,lr} @ save registers
cmp r0,#0
beq 100f
mov r2,r0
blx r1 @ call function
ldr r0,[r2,#node_left]
bl preOrder
ldr r0,[r2,#node_right]
bl preOrder
100:
pop {r1-r2,lr} @ restaur registers
bx lr
/******************************************************************/
/* display node */
/******************************************************************/
/* r0 contains node address */
displayElement: @ INFO: displayElement
push {r1,r2,r3,lr} @ save registers
mov r2,r0
ldr r1,iAdrsZoneConv
bl conversion16
mov r4,#0
strb r4,[r1,r0]
ldr r0,iAdrszMessResult
ldr r1,iAdrsZoneConv
bl strInsertAtCharInc
mov r3,r0
ldr r0,[r2,#node_left]
ldr r1,iAdrsZoneConv
bl conversion16
mov r4,#0
strb r4,[r1,r0]
mov r0,r3
ldr r1,iAdrsZoneConv
bl strInsertAtCharInc
mov r3,r0
ldr r0,[r2,#node_right]
ldr r1,iAdrsZoneConv
bl conversion16
mov r4,#0
strb r4,[r1,r0]
mov r0,r3
ldr r1,iAdrsZoneConv
bl strInsertAtCharInc
mov r3,r0
ldr r0,[r2,#node_value]
ldr r1,iAdrsZoneConv
bl conversion10
mov r4,#0
strb r4,[r1,r0]
mov r0,r3
ldr r1,iAdrsZoneConv
bl strInsertAtCharInc
mov r3,r0
ldr r0,[r2,#node_height]
ldr r1,iAdrsZoneConv
bl conversion10
mov r4,#0
strb r4,[r1,r0]
mov r0,r3
ldr r1,iAdrsZoneConv
bl strInsertAtCharInc
mov r3,r0
ldr r0,[r2,#node_parent]
ldr r1,iAdrsZoneConv
bl conversion16
mov r4,#0
strb r4,[r1,r0]
mov r0,r3
ldr r1,iAdrsZoneConv
bl strInsertAtCharInc
bl affichageMess
100:
pop {r1,r2,r3,lr} @ restaur registers
bx lr @ return
iAdrszMessResult: .int szMessResult
iAdrsZoneConv: .int sZoneConv
iAdrsValue: .int sValue
/******************************************************************/
/* memory allocation on the heap */
/******************************************************************/
/* r0 contains the size to allocate */
/* r0 returns address of memory heap or - 1 if error */
/* CAUTION : The size of the allowance must be a multiple of 4 */
allocHeap:
push {r5-r7,lr} @ save registers
@ allocation
mov r6,r0 @ save size
mov r0,#0 @ read address start heap
mov r7,#0x2D @ call system 'brk'
svc #0
mov r5,r0 @ save address heap for return
add r0,r6 @ reservation place for size
mov r7,#0x2D @ call system 'brk'
svc #0
cmp r0,#-1 @ allocation error
movne r0,r5 @ return address memory heap
pop {r5-r7,lr} @ restaur registers
bx lr @ return
/***************************************************/
/* ROUTINES INCLUDE */
/***************************************************/
.include "../affichage.inc"