-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsierpinski.asm
180 lines (130 loc) · 2.31 KB
/
sierpinski.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
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
%include "lib/stdlib.asm"
; --------- SETUP --------------
DELAY equ 50 ; ms
WIDTH equ 200 ; line length
HEIGHT equ 10000 ; n steps
CH_0 equ '.' ; false char
CH_1 equ "o" ; true char
; --------- END-SETUP --------------
; compute numerical value of state given booleans prev, curr and next
%define state(prev, curr, next) (100 * CH_%+prev + 10 * CH_%+curr + CH_%+next)
; initialize board
%macro init 1
pusha
mov rsi, %1
mov rcx, rsi
add rcx, WIDTH + 2
%%_init:
mov [rsi], byte CH_0
mov [rdi], byte CH_0
inc rsi
inc rdi
cmp rsi, rcx
jbe %%_init
popa
%endmacro
global _start
section .bss
board1 resb WIDTH + 2 ; 2 bytes for edges
board2 resb WIDTH + 2
section .text
_start:
; initial setup
mov rsi, board1
mov rdi, board2
init rsi
init rdi
; set middle element to 1
mov byte [rsi + WIDTH / 2 + 1], CH_1
mov rcx, HEIGHT
_loop:
call printbrd ; print current state
call step ; generate new state
xchg rsi, rdi ; swap pointers
; only call SYS_NANOSLEEP if there is any actual delay set
%if DELAY != 0
sleep 0, DELAY * 1_000_000
%endif
loop _loop ; rinse and repeat
exit
; --------- UTILS --------------
; print board
; input ptr: RSI
printbrd:
pusha
inc rsi
mov rax, SYS_WRITE
mov rdi, STDOUT
mov rdx, WIDTH + 1
syscall
putc NEWL
popa
ret
; generate new automaton state
; input ptr: RSI
; output ptr: RDI
step:
pusha
push r8
push r9
; move one cell right so prev is not undefined
inc rsi
inc rdi
; width limit
mov r9, rsi
add r9, WIDTH
_step:
; get value of prev, curr and next
xor r8, r8
; prev
xor rax, rax
mov al, [rsi - 1]
mov rbx, 100
mul rbx
add r8, rax
; curr
xor rax, rax
mov al, [rsi]
mov rbx, 10
mul rbx
add r8, rax
; next
xor rax, rax
mov al, [rsi + 1]
add r8, rax
; main logic
cmp r8, state(1, 1, 1)
jz _sfalse
cmp r8, state(1, 1, 0)
jz _strue
cmp r8, state(1, 0, 1)
jz _sfalse
cmp r8, state(1, 0, 0)
jz _strue
cmp r8, state(0, 1, 1)
jz _strue
cmp r8, state(0, 1, 0)
jz _sfalse
cmp r8, state(0, 0, 1)
jz _strue
cmp r8, state(0, 0, 0)
jz _sfalse
abort ; shouldn't happen
_sret:
; increment pointers
inc rsi
inc rdi
cmp rsi, r9
jbe _step
pop r9
pop r8
popa
ret
; set current cell to 0
_sfalse:
mov [rdi], byte CH_0
jmp _sret
; set current cell to 1
_strue:
mov [rdi], byte CH_1
jmp _sret