-
Notifications
You must be signed in to change notification settings - Fork 0
/
day05-part1.asm
128 lines (115 loc) · 4.77 KB
/
day05-part1.asm
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
.global main
.section .rodata
filename:
.string "inputs/day05"
#.string "inputs/day05-test"
.section .text
main:
la a0, filename
call map_input_file
mv s0, a0
add s11, a0, a1
# compute number of stacks from first line length
# (all start stacks input lines have the same length)
call line_length
addi a0, a0, 1
li t0, 4
div s1, a0, t0 # s1 contains number of stacks
mv s3, a0 # s3 contains line length
# allocate a vector of pointers for the stacks
mv a0, s1
li a1, 8
call calloc
mv s2, a0 # s2 contains the vector's address
# store line start addresses on The Stack to process lines in reverse order
addi sp, sp, -8
sd zero, 0(sp)
addi s0, s0, 1 # skip first character
li t1, 49 # '1'
loop_store:
lb t0, 0(s0)
beq t0, t1, loop_store_end # stacks number line reached
addi sp, sp, -8
sd s0, 0(sp)
add s0, s0, s3 # add line length to pointer
j loop_store
loop_store_end:
# build stacks as linked lists
loop_lines:
mv s3, s2 # stacks vector pointer
mv s4, s1 # stacks countdown
ld s6, 0(sp) # pop line address from The Stack
addi sp, sp, 8
beqz s6, loop_lines_end # null address poped, no more lines to process
loop_stacks:
lb s5, 0(s6) # read crate letter or space if no crate
li t0, 32 # ' '
beq s5, t0, skip_push # no stack element here
li a0, 9 # allocate linked list node
call malloc
ld t0, 0(s3) # load addr of head linked list node
sb s5, 0(a0) # store stack element on node
sd t0, 1(a0) # store head node addr as current node's next node addr
sd a0, 0(s3) # current node is new head node
skip_push:
addi s4, s4, -1 # decrement countdown
beqz s4, loop_lines # countdown reached 0, move on to next line
addi s3, s3, 8 # point to next stack's ll head
addi s6, s6, 4 # skip to next stack element
j loop_stacks
loop_lines_end:
# move input pointer to the movements part
mv a0, s0
call skip_to_next_line
addi a0, a0, 1
# apply movements
li s8, 8
loop_movements:
addi a0, a0, 5 # skip "move "
call parse_integer
mv s3, a1 # s3 contains number of crates to move
addi a0, a0, 6 # skip " from "
call parse_integer
mv s4, a1
addi s4, s4, -1 # convert stack number to index
mul s4, s4, s8
add s4, s4, s2 # s4 points to "from" stack
addi a0, a0, 4 # skip " to "
call parse_integer
mv s5, a1
addi s5, s5, -1 # convert stack number to index
mul s5, s5, s8
add s5, s5, s2 # s5 points to "to" stack
addi a0, a0, 1 # skip "\n"
loop_onemove:
ld t0, 0(s4) # load address of top crate in "from" stack
ld t1, 0(s5) # load address of top crate in "to" stack
ld t2, 1(t0) # load address of second crate in "from" stack
sd t2, 0(s4) # second crate of "from" stack is now top crate
sd t0, 0(s5) # moved crate is now top crate in "to" crate
sd t1, 1(t0) # top crate in "to" stack is now second crate
addi s3, s3, -1 # one less crate to move
bnez s3, loop_onemove
blt a0, s11, loop_movements
# display answer
addi sp, sp, -2
sb zero, 1(sp)
li t0, 10 # '\n'
sb t0, 0(sp)
sub sp, sp, s1 # allocate one char per stack in the stack
li a7, 64 # write
li a0, 0 # stdout
mv a1, sp # point to start of string
addi a2, s1, 1 # one char per stack + '\n'
loop_char:
ld t1, 0(s2) # load address of top crate
lb t0, 0(t1) # load letter
sb t0, 0(sp) # copy letter to The Stack
addi s2, s2, 8 # move to next stack
addi sp, sp, 1 # move to next character
addi s1, s1, -1 # decrease stacks countdown
bnez s1, loop_char
ecall
li a7, 93 # exit
li a0, 0 # EXIT_SUCCESS
ecall