Single Linked Lists and Quiz 15
Implement the following C program in assembly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <stdio.h>
struct ListNode
{
struct ListNode *next;
char id;
};
struct ListNode c, a, b;
int printList(const struct ListNode *listNode);
int
main(void)
{
a.id = 'a';
a.next = &b;
b.id = 'b';
b.next = &c;
c.id = 'c';
c.next = 0;
printList(&a);
putchar('\n');
}
int
printList(const struct ListNode *listNode)
{
for (; listNode; listNode = listNode->next) {
putchar(listNode->id);
}
return 1; // because we need to return something
}
|
Of course the function call putchar() can be realized with a putc instruction.
You program should generate the same output as the assmbler program created by gcc:
theon$ gcc list.c theon$ ./a.out abc theon$
Or ucc:
theon$ ucc list.c theon$ ./a.out abc theon$
Submit your assembly program _list.s- with:
1 | submit hpc quiz15 isa.txt list.s
|
There are no automatic tests (no message/email means your submit succeeded).
Provided Material: Skeleton
You can use the instruction set from Session 14 and this skeleton:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | # calling conventions
.equ FP, 1
.equ SP, 2
.equ RET_ADDR, 3
.equ ret, 0
.equ fp, ret + 8
.equ rval, fp + 8
.equ fparam0, rval + 8
.equ fparam1, fparam0 + 8
.equ local0, -8
.equ local1, local0 - 8
# for the demo
.equ FUNC_ADDR, 4
/*
* function: _start
*/
_start:
ldzwq 0, %SP
# call: int main(void)
subq 8 * (3 + 0), %SP, %SP
ldzwq main, %FUNC_ADDR
call %FUNC_ADDR, %RET_ADDR
movq rval(%SP), %4 # return value in %4
addq 8 * (3 + 0), %SP, %SP
halt %4 # halt with return value
/*
struct ListNode c, a, b;
*/
.bss
.align 8
a:
.space 9
.align 8
b:
.space 9
.align 8
c:
.space 9
/*
* function: int main(void)
*/
.text
#
# pool for main
#
.align 8
.main.pool
.main.pool.a
.quad a
.main.pool.b
.quad b
.main.pool.c
.quad c
.main.pool.printList
.quad printList
#
# offsets for pool members
#
.equ p.a, (.main.pool.a - .main.pool) / 8
.equ p.b, (.main.pool.b - .main.pool) / 8
.equ p.c, (.main.pool.c - .main.pool) / 8
.equ p.printList, (.main.pool.printList - .main.pool) / 8
.text
main:
// prologue
movq %RET_ADDR, ret(%SP)
movq %FP, fp(%SP)
movq %SP, %FP
subq 8 * 1, %SP, %SP
.equ n, local0
// body
# a.id = 'a';
ldzwq 'a', %4
ldpa .main.pool, %5
ldfp p.a(%5), %5
movb %4, 8(%5)
# a.next = &b;
# b.id = 'b';
# b.next = &c;
# c.id = 'c';
# c.next = 0;
# printList(&a);
# putchar('\n');
# return 0;
.main.ret
// epilogue
movq %FP, %SP
movq fp(%SP), %FP
movq ret(%SP), %RET_ADDR
ret %RET_ADDR
/*
* function: int printList(const struct ListNode *listNode)
*/
.text
printList:
// prologue
movq %RET_ADDR, ret(%SP)
movq %FP, fp(%SP)
movq %SP, %FP
subq 8 * 0, %SP, %SP
.equ listNode, fparam0
// body
# for (; listNode; listNode = listNode->next) {
# putchar(listNode->id);
# }
# return 1;
// epilogue
movq %FP, %SP
movq fp(%SP), %FP
movq ret(%SP), %RET_ADDR
ret %RET_ADDR
|
In listquiz15.s_ the definition
1 | struct ListNode c, a, b;
|
of the uninitialized global variables a, b and c in the BSS segment is already realized. Also the statement
1 | a.id = 'a';
|
is already implemented.