struct Node definition used in using ARM assembler programming examples:
struct Node { int value1; // Data field 1 offset = 0 short value2; // Data field 2 offset = 4 short value3; // Data field 3 offset = 6 struct Node *next; // Link field offset = 8 } |
Background information:
|
How I created a linked list using assembler directives:
Example of a linked list with 5 nodes:
p0: .4byte 333 // Object [333,23,33,p2]
.2byte 23, 33
.4byte p2
.skip 4 // gap
p1: .4byte 111 // Object [111,21,31,p3]
.2byte 21, 31
.4byte p3
p2: .4byte 444 // Object [444,24,34,p4]
.2byte 24, 34
.4byte p4
.skip 4 // gap
p3: .4byte 222 // Object [222,22,32,p0]
.2byte 22, 32
.4byte p0
.skip 4 // gap
p4: .4byte 555 // Object [555,25,35,null]
.2byte 25, 35
.4byte 0 // 0 = null
head: .4byte p1
|
The first list element (= node) is p1 !! (Can you see it ?)
The assembler directives created the following linked list:
head ⇒ [111,21,31,•]⇒[222,22,32,•] ⇒[333,23,33,•]⇒[444,24,34,•]⇒[555,25,35,null]
p0: .4byte 333 // Object [333,23,33,p2] .2byte 23, 33 .4byte p2 .skip 4 // gap p1: .4byte 111 // Object [111,21,31,p3] .2byte 21, 31 .4byte p3 p2: .4byte 444 // Object [444,24,34,p4] .2byte 24, 34 .4byte p4 .skip 4 // gap p3: .4byte 222 // Object [222,22,32,p0] .2byte 22, 32 .4byte p0 .skip 4 // gap p4: .4byte 555 // Object [555,25,35,null] .2byte 25, 35 .4byte 0 // 0 = null head: .4byte p1 // head contains address p1 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Given the following struct Node (object) definition:
struct Node { int value1; // Data field 1 short value2; // Data field 2 short value3; // Data field 3 List next; // Link field }; |
The offset of the fields in objects defined by the above class definition are:
Offset(value1) = 0 Offset(value2) = 4 Offset(value3) = 6 (4+2) Offset(next) = 8 (4+2+2) |
We now discuss how to access a list element using ARM assembler code
Write
ARM assembler code to:
|
![]() |
ARM assembler instructions: // Fetch: head.value1, 2 and 3 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
The variables value1, value2 and value3 are fetched using load instructions with their corresponding offsets:
![]() |
ARM assembler instructions: // Fetch: head.value1, 2 and 3 // Preparation: // r0 = |
Required preparation : r0 = base address of the first Node "object" (struct)
The variable head contains the base address of the first Node "object" (struct):
![]() |
ARM assembler instructions: // Fetch: head.value1, 2 and 3 // Preparation: // r0 = head ldr r1, [r0, #0]//Offset(v1)=0 ldrsh r2, [r0, #4]//Offset(v2)=4 ldrsh r3, [r0, #6]//Offset(v3)=6 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Solution: assembler code to load (= fetch) head.value1,value2,value3 into registers R1, R2, R3:
![]() |
ARM assembler instructions: // Fetch: head.value1, 2 and 3 movw r0, #:lower16:head movt r0, #:upper16:head ldr r0, [r0] // R0 = |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Write
assembler code to:
|
![]() |
ARM assembler instructions: // Fetch: head.next.val1, 2 and 3 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
The variables value1, value2 and value3 are fetched using load instructions with their corresponding offsets:
![]() |
ARM assembler instructions: // Fetch: head.next.val1, 2 and 3 // Preparation: // r0 = |
Required preparation : r0 = base address of the 2nd Node "object" (struct)
The base address of the 2nd list object is stored in the variable head.next:
![]() |
ARM assembler instructions: // Fetch: head.next.val1, 2 and 3 // Preparation: // r0 = head.next ldr r1, [r0, #0]//Offset(v1)=0 ldrsh r2, [r0, #4]//Offset(v2)=4 ldrsh r3, [r0, #6]//Offset(v3)=6 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
We must start by fetching head in register R0:
![]() |
ARM assembler instructions: // Fetch: head.next.val1, 2 and 3 // Preparation: // r0 = head.next movw r0, #:lower16:head movt r0, #:upper16:head ldr r0, [r0] // r0=head ldr r1, [r0, #0]//Offset(v1)=0 ldrsh r2, [r0, #4]//Offset(v2)=4 ldrsh r3, [r0, #6]//Offset(v3)=6 |
Then: use R0 to fetch head.next (next has offset=8) into R0 !!!
Complete solution: assembler code to load (= fetch) head.value1,value2,value3 into registers R1, R2, R3:
![]() |
ARM assembler instructions: // Fetch: head.next.val1, 2 and 3 // Preparation: // r0 = head.next movw r0, #:lower16:head movt r0, #:upper16:head ldr r0, [r0] // r0=head ldr r0, [r0,#8] // r0= |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Fetch the following variable into register R1:
r1 = head.next.next.value2 |
Solution:
|
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Fetch the following variable into register R1:
r1 = head.next.next.value2 |
Solution:
movw r0, #:lower16:head movt r0, #:upper16:head ldr r0, [r0] // r0 = head |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Fetch the following variable into register R1:
r1 = head.next.next.value2 |
Solution:
movw r0, #:lower16:head movt r0, #:upper16:head ldr r0, [r0] // r0 = head ldr r0, [r0, #8] // r0 = head.next |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Fetch the following variable into register R1:
r1 = head.next.next.value2 |
Solution:
movw r0, #:lower16:head
movt r0, #:upper16:head
ldr r0, [r0] // r0 = head
ldr r0, [r0, #8] // r0 = head.next
ldr r0, [r0, #8] // r0 = head.next.next
// We now have: r0 = base address of the required list object
|
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Fetch the following variable into register R1:
r1 = head.next.next.value2 |
Solution:
movw r0, #:lower16:head movt r0, #:upper16:head ldr r0, [r0] // r0 = head ldr r0, [r0, #8] // r0 = head.next ldr r0, [r0, #8] // r0 = head.next.next ldrsh r1, [r0, #4] // r1 = head.next.next.value2 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.next.next.value2 = 99; |
Solution:
|
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.next.next.value2 = 99; |
Solution:
// Get the RHS first mov r0, #99 // r0 = 99 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.next.next.value2 = 99; |
Solution:
// Get the RHS first mov r0, #99 // r0 = 99 // Preparation: base address r1 = head.next.next |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.next.next.value2 = 99; |
Solution:
// Get the RHS first mov r0, #99 // r0 = 99 // Preparation: base address r1 = head.next.next movw r1, #:lower16:head movt r1, #:upper16:head // r1 = addr(head) ldr r1, [r1] // r1 = head |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.next.next.value2 = 99; |
Solution:
// Get the RHS first mov r0, #99 // r0 = 99 // Preparation: base address r1 = head.next.next movw r1, #:lower16:head movt r1, #:upper16:head // r1 = addr(head) ldr r1, [r1] // r1 = head ldr r1, [r1, #8] // r1 = head.next |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.next.next.value2 = 99; |
Solution:
// Get the RHS first
mov r0, #99 // r0 = 99
// Preparation: base address r1 = head.next.next
movw r1, #:lower16:head
movt r1, #:upper16:head // r1 = addr(head)
ldr r1, [r1] // r1 = head
ldr r1, [r1, #8] // r1 = head.next
ldr r1, [r1, #8] // r1 = head.next.next
// We now have: r1 = base address of the required list object
|
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.next.next.value2 = 99;
|
Solution:
// Get the RHS first mov r0, #99 // r0 = 99 // Preparation: base address r1 = head.next.next - DONE ! movw r1, #:lower16:head movt r1, #:upper16:head // r1 = addr(head) ldr r1, [r1] // r1 = head ldr r1, [r1, #8] // r1 = head.next ldr r1, [r1, #8] // r1 = head.next.next strh r0, [r1, #4] // Offset(value2) = 4 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.value1 = head.next.next.value3; |
Solution:
// Get head.next.next.value3 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.value1 = head.next.next.value3; |
Solution:
// Get head.next.next.value3 movw r0, #:lower16:head movt r0, #:upper16:head // r0 = addr(head) ldr r0, [r0] // r0 = head |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.value1 = head.next.next.value3; |
Solution:
// Get head.next.next.value3 movw r0, #:lower16:head movt r0, #:upper16:head // r0 = addr(head) ldr r0, [r0] // r0 = head ldr r0, [r0, #8] // r0 = head.next |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.value1 = head.next.next.value3; |
Solution:
// Get head.next.next.value3 movw r0, #:lower16:head movt r0, #:upper16:head // r0 = addr(head) ldr r0, [r0] // r0 = head ldr r0, [r0, #8] // r0 = head.next ldr r0, [r0, #8] // r0 = head.next.next |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.value1 = head.next.next.value3; |
Solution:
// Get head.next.next.value3 movw r0, #:lower16:head movt r0, #:upper16:head // r0 = addr(head) ldr r0, [r0] // r0 = head ldr r0, [r0, #8] // r0 = head.next ldr r0, [r0, #8] // r0 = head.next.next ldrsh r0, [r0, #6] // r0 = head.next.next.value3 // Store r0 in head.value1 |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.value1 = head.next.next.value3; |
Solution:
// Get head.next.next.value3 movw r0, #:lower16:head movt r0, #:upper16:head // r0 = addr(head) ldr r0, [r0] // r0 = head ldr r0, [r0, #8] // r0 = head.next ldr r0, [r0, #8] // r0 = head.next.next ldrsh r0, [r0, #6] // r0 = head.next.next.value3 // Store r0 in head.value1 movw r1, #:lower16:head movt r1, #:upper16:head // r0 = addr(head) ldr r1, [r1] // r0 = head |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s
Translate the following assignment statement into ARM assembler:
head.value1 = head.next.next.value3; |
Solution:
// Get head.next.next.value3 movw r0, #:lower16:head movt r0, #:upper16:head // r0 = addr(head) ldr r0, [r0] // r0 = head ldr r0, [r0, #8] // r0 = head.next ldr r0, [r0, #8] // r0 = head.next.next ldrsh r0, [r0, #6] // r0 = head.next.next.value3 // Store r0 in head.value1 movw r1, #:lower16:head movt r1, #:upper16:head // r0 = addr(head) ldr r1, [r1] // r0 = head str r0, [r1, #0] // offset(value1) = 0 (int) |
DEMO: /home/cs255001/demo/asm/4-linked-list/demo2.s