-
Notifications
You must be signed in to change notification settings - Fork 0
/
12b.s
269 lines (210 loc) · 4.4 KB
/
12b.s
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
section .text
extern writeNewline, writeLong, findChar, alloc
global _start:function
_start:
; get first argument
mov rdi, [rsp + 16]
mov rax, 2 ; open inputFile
; mov rdi, rdi ; already have input file name
mov rsi, O_RDONLY
mov rdx, 0
syscall
mov rdi, rax ; fstat opened inputFile
mov rax, 5
mov rsi, statBuf
syscall
mov rsi, [statBuf + sizeOffset] ; rsi = length of file
mov r12, rdi ; r12 = fd
mov rax, 9 ; mmap the file
mov rdi, 0
; mov rsi, rsi ; already have size of file
mov rdx, PROT_READ
mov r10, MAP_PRIVATE
mov r8, r12
mov r9, 0
syscall
mov r15, rax ; r15 = current position in file
mov rax, 3 ; close file
mov rdi, r12
syscall
mov rcx, 0 ; insert into links table both directions of the link
.readLoop:
mov di, [r15] ; get first end of link
mov [links + (rcx * (2+2) * 2) + 0], di
mov [links + (rcx * (2+2) * 2) + 6], di
lea rdi, [r15 + 2] ; skip to the dash
mov sil, '-'
call findChar
lea r15, [rax + 1]
mov di, [r15] ; get second end of link
mov [links + (rcx * (2+2) * 2) + 2], di
mov [links + (rcx * (2+2) * 2) + 4], di
lea rdi, [r15 + 2] ; skip to the newline
mov sil, 0xa
call findChar
lea r15, [rax + 1]
inc rcx
cmp rcx, 26
jl .readLoop
mov di, [st]
mov rsi, 0
call countPaths
mov rdi, rax
call writeLong
call writeNewline
mov rax, 60 ; return 0
mov rdi, 0
syscall
;; di = current link id
;; rsi = linked list of vistied links
;; returns number of paths to 'en' link
;; clobbers everything
countPaths:
push r12 ; r12w = current link id
mov r12w, di
push r13 ; r13 = linked list of visited links
mov r13, rsi
push r14 ; r14 = linked list of connected nodes (initialized later)
push r15
mov r15, 0 ; r15 = return value
call cannotVisit
test rax, rax
mov rdx, 0
cmovnz rax, rdx
jnz .done
cmp r12w, [en]
mov rdx, 1
cmove rax, rdx
je .done
mov rdi, 16 ; r13 = (cons node path)
call alloc
mov [rax + 0], r12w
mov [rax + 8], r13
mov r13, rax
mov di, r12w
call findLinks
mov r14, rax
; for each link in the linked list (at least one, since we got here)
.linkLoop:
mov di, [r14 + 0]
mov rsi, r13
call countPaths
add r15, rax
mov r14, [r14 + 8] ; next node in the linked list
test r14, r14
jnz .linkLoop
mov rax, r15
.done:
pop r15
pop r14
pop r13
pop r12
ret
;; di = current link id
;; rsi = linked list of visited links
;; clobbers everything
cannotVisit:
push r10 ; r10w = current link id
mov r10w, di
push r11 ; r11 = linked list of visited links
mov r11, rsi
; is this uppercase? (i.e. less than 'Z'?)
mov rdx, 0
cmp r10b, 'Z'
cmovbe rax, rdx
jbe .done
; is this a member of the path?
mov rax, 0
mov rsi, r11
.loop:
test rsi, rsi
jz .done ; no - return zero
cmp r10w, [rsi + 0]
je .maybeCant ; yes - maybe return one
mov rsi, [rsi + 8]
jmp .loop
.maybeCant:
mov rax, 1
cmp r10w, [st] ; is this 'st'?
je .done
cmp r10w, [en] ; is this 'en'?
je .done ; return true if so (node is special and is already on the path)
mov rdi, r11 ; return if there's already a duplicate
call hasDuplicate
.done:
pop r11
pop r10
ret
;; rdi = linked list
;; returns if the list has a duplicate lowercase id
;; clobbers everything
hasDuplicate:
mov rax, 0
mov rdx, 1
.outerLoop:
cmp rdi, 0
jz .done
mov r8w, [rdi + 0] ; get value of node
; skip nodes if it's uppercase
cmp r8b, 'Z'
jbe .doneInner
mov rsi, [rdi + 8] ; is this node in the rest of the list?
.innerLoop:
cmp rsi, 0
jz .doneInner
cmp r8w, [rsi + 0]
cmove rax, rdx
je .done
mov rsi, [rsi + 8]
jmp .innerLoop
.doneInner:
mov rdi, [rdi + 8] ; next node
jmp .outerLoop
.done:
ret
;; di = current link id
;; clobbers everything
findLinks:
push r15 ; r15 = return value
mov r15, 0
push r14 ; r14 = link list index
mov r14, 0
push r13 ; r13 = current link id
mov r13w, di
; for each link in the table
.loop:
cmp r13w, [links + (r14 * (2+2)) + 0]
jne .continue
mov rdi, 16
call alloc
mov [rax + 8], r15
mov r15, rax
mov di, [links + (r14 * (2+2)) + 2]
mov [r15 + 0], di
.continue:
inc r14
cmp r14, 26*2
jl .loop
mov rax, r15
pop r13
pop r14
pop r15
ret
section .rodata
sizeOffset: equ 48
O_RDONLY: equ 0
PROT_READ: equ 1
MAP_PRIVATE: equ 2
st:
db 'st'
en:
db 'en'
section .bss
statBuf:
resb 144
;; struct link {
;; char[2] from;
;; char[2] to;
;; }
links:
resb 26*2*(2+2)