-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbrainfuck.s
382 lines (272 loc) · 6.61 KB
/
brainfuck.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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
.global brainfuck
#TODO : MAKE THE CODE BLOCK EXECUTABLE + FIX THE END LOOP
charPrint: .asciz "%c"
format_str: .asciz "We should be executing the following code:\n%s"
input: .asciz "%c"
debug: .asciz "PLEASE WORK %d \n"
# Your brainfuck subroutine will receive one argument:
# a zero termianted string containing the code to execute.
brainfuck:
pushq %rbp
movq %rsp, %rbp
call compile
pushq %rax
movq $10000000, %rdi
call malloc
movq %rax, %rdi
popq %r10
jmp *%r10
movq $0, %rdi
movq %rbp, %rsp
popq %rbp
ret
call exit
#Allocate memory for the instructions
compile:
#Prologue
pushq %rbp
movq %rsp, %rbp
#Store registers to set them back to what they were
pushq %r12
pushq %r15
pushq %r14
pushq %r13
pushq %r11
pushq %r9
movq %rdi, %r15
movq $0, %r14
movq $0, %r11
#Create space and map to use like an array[] for the instructions using
# mmap() c function. args : ( *address, length, protect, flags, filedes, offset)
movq $0, %rdi # *address
shl $4, %rsi # shift left by 4 bits so that we can allocate 8 bytes per character/command/instruction
movq $6, %rdx #Protection : Read and Write
movq $0x22, %rcx #mapping flag
movq $-1, %r8 #no dile descriptor
movq $0, %r9 #0 offset we want to start at the beggining
call mmap
movq %rax, %r13 # address of first memory space
pushq %r13
prologueMaker:
mov $0xEC894855, (%r13) #mov %rbp, %rsp + pushq %rbp
addq $4, %r13
movq $0x5741, (%r13) #pushq %r15
addq $2, %r13
movq $0x5641, (%r13) #pushq %r14
addq $2, %r13
movq $0xff8949, (%r13) #movq %rdi, %r15
addq $3, %r13
movq $0x00e68349, (%r13) #and $0, %r14
addq $4, %r13
#Loads the next instruction/character/command into %dil (rdi) 1 byte
parsingLoop:
movb (%r15, %r14), %dil
#Parsing switch logic, we check what character we are dealing with
# Check for different possible cases, ignore if not part of the cases.
cmpb $0, %dil
je endOfParsing
cmpb $46, %dil # "." Print character
je printChar
cmpb $44, %dil # "," Get character
je getChar
cmpb $43, %dil # "+" Increase value at a ddress
je incrVal
cmpb $45, %dil # "-" Decrease value at address
je decrVal
cmpb $91, %dil # "[" Set up looping point
je loopStart
cmpb $93, %dil # "]" Jump back to looping point
je loopEnd
cmpb $60, %dil # "<" Decrease address pointer
je prevAddr
cmpb $62, %dil # ">" Increase address pointer
je nextAddr
incq %r14
jmp parsingLoop
printChar:
incq %r14 #increment our instruction pointer
movq $0x00e68348, (%r13) #and $0, %rsi
addq $4, %r13
movq $0x37348a43, (%r13) #movb (%r15, %r14, 1), %sil
addq $4, %r13
movq $0xBA49, (%r13) #movq $$printCharFunc, %r10
addq $2, %r13
movq $printCharFunc, (%r13)
addq $8, %r13
movq $0xD2FF41, (%r13) #call *%r10
addq $3, %r13
jmp parsingLoop
getChar:
movq $0xBA49, (%r13) #movq $getCharFunc, %r10
addq $2, %r13
movq $getCharFunc, (%r13)
addq $8, %r13
movq $0xD2FF41, (%r13) #call *%r10
addq $3, %r13
incq %r14 #increment our instruction pointer
jmp parsingLoop
decrVal:
movq $-1, %r12 #we start at -1 if we come from a -
jmp findPattern
incrVal:
movq $1, %r12
#OPTIMISATION check for sequence of + or -
findPattern:
incq %r14
cmpb $43, (%r15, %r14, 1)
je plus
cmpb $45, (%r15, %r14, 1)
je minus
cmpb $10, (%r15, %r14, 1)
je findPattern
jmp end
plus:
addq $1, %r12
jmp findPattern
minus:
subq $1, %r12
jmp findPattern
end:
#add r12 to the location
cmpq $0, %r12
je parsingLoop
movq $0x3704814b, (%r13) #addq (value at r12), (%r15, %r14, 1)
addq $4, %r13
movq %r12, (%r13)
addq $4, %r13
movq $0, %r12
jmp parsingLoop
loopStart:
# emptySpaceCheck:
#
# cmpb $10, 1(%r15, %r14, 1)
# je firstEmptySpace
# cmpb $10, 2(%r15, %r14, 1)
# je secondEmptySpace
#
noEemptySpace:
cmpb $45, 1(%r15, %r14,1)
jne normalCase
cmpb $93, 2(%r15, %r14, 1)
jne normalCase
#
# firstEmptySpace:
# cmpb $45, 2(%r15, %r14,1)
# jne normalCase
# cmpb $93, 3(%r15, %r14, 1)
# jne normalCase
#
# secondEmptySpace:
# cmpb $45, 1(%r15, %r14, 1)
# jne normalCase
# cmpb $93, 3(%r15, %r14, 1)
# jne normalCase
#jmp normalCase
zeroCell:
movq $0x003704c643, (%r13) #movb $0, (%r15, %r14, 1)
addq $5, %r13
addq $3, %r14
jmp parsingLoop
normalCase:
pushq %r13
mov $0x00373c8043, (%r13)
addq $5, %r13
movq $0x840f, (%r13)
addq $6, %r13
incq %r14
jmp parsingLoop
copyLoop:
loopEnd:
mov $0x00373c8043, (%r13) #cmpb $0, (%r15, %r14, 1)
addq $5, %r13
movq $0x850f, (%r13) #jne begin
addq $2, %r13
popq %r12 #get start loop address
movq %r13, %rax
subq %r12, %rax #Calculate jump (current - old)
subq $7, %rax
mov %eax, 7(%r12) #Add it to begining loop so we know where to jump if 0
negq %rax #reverse it
mov %eax, (%r13) #add jump to restart
addq $4, %r13
incq %r14
jmp parsingLoop
prevAddr:
movq $-1, %r12 #we start at -1 if we come from a -
jmp findPatternAddr
nextAddr:
movq $1, %r12
#OPTIMISATION check for sequence of + or -
findPatternAddr:
incq %r14
cmpb $62, (%r15, %r14, 1)
je plusAddr
cmpb $60, (%r15, %r14, 1)
je minusAddr
cmpb $10, (%r15, %r14, 1)
je findPatternAddr
jmp endAddr
plusAddr:
addq $1, %r12
jmp findPatternAddr
minusAddr:
subq $1, %r12
jmp findPatternAddr
endAddr:
#add r12 to the location
cmpq $0, %r12
je parsingLoop
movq $0xc68149, (%r13) #addq (value at r12), %r14
addq $3, %r13
movq %r12, (%r13)
addq $4, %r13
movq $0, %r12
jmp parsingLoop
endOfParsing:
#retrun registers that are used to what they used to be
movq $0x5f415e41, (%r13) #popq r14 - r15
addq $4, %r13
movq $0x5de58b48, (%r13)
addq $4, %r13
movq $0xc3, (%r13)
addq $1, %r13
popq %r12 #first address of memory
movq %r13, %rsi
subq %r12, %rsi
mov %r12, %rdi
mov $4, %rdx
call mprotect
popq %r13
popq %r14
popq %r15
movq %r12, %rax
popq %r12
#Epilogue
movq %rbp, %rsp
popq %rbp
ret
printCharFunc:
pushq %rbp
movq %rsp, %rbp
movq $0, %rax
movq $charPrint, %rdi
call printf
movq %rbp, %rsp
popq %rbp
ret
getCharFunc:
push %rbp
mov %rsp, %rbp
push %rdi
subq $8, %rsp
movq $0, %rax
movq $input, %rdi
leaq -8(%rbp), %rsi
call scanf
movq -8(%rbp), %rdi
movb %dil, (%r15, %r14, 1)
addq $8, %rsp
pop %rdi
mov %rbp, %rsp
pop %rbp
ret