-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfizzbuzz.asm
154 lines (116 loc) · 3.93 KB
/
fizzbuzz.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
; FizzBuzz in assembly
section .data
nl db 0x0a
fizz db 'Fizz'
fizz_len equ $-fizz
buzz db 'Buzz'
buzz_len equ $-buzz
iterations equ 100
section .text
global _start
_start:
; local variables:
push 0 ; the iteratotion variable [rsp]
loop_body:
cmp dword [rsp], iterations
jg after_loop
mov rdx, 0 ; clear remainder
mov rax, qword [rsp] ; divided
mov rcx, qword 15 ; divisor
div rcx ; result is in rax, remainder is in rdx
cmp rdx, 0
je if_divisible_by_15
mov rdx, 0 ; clear remainder
mov rax, qword [rsp] ; divided
mov rcx, qword 5 ; divisor
div rcx ; result is in rax, remainder is in rdx
cmp rdx, 0
je if_divisible_by_5
mov rdx, 0 ; clear remainder
mov rax, qword [rsp] ; divided
mov rcx, qword 3 ; divisor
div rcx ; result is in rax, remainder is in rdx
cmp rdx, 0
je if_divisible_by_3
jmp else_block
if_divisible_by_15:
call print_fizz
call print_buzz
call print_nl
jmp end_if
if_divisible_by_5:
call print_buzz
call print_nl
jmp end_if
if_divisible_by_3:
call print_fizz
call print_nl
jmp end_if
else_block:
mov rdi, [rsp]
call print_number
call print_nl
end_if:
add dword [rsp], 1
jmp loop_body
after_loop:
; deallocate local variables
add rsp, 8 ; remove iteration variable
mov rax, 60 ; syscall number, 60 = exit
mov rdi, 0 ; exit code
syscall
print_nl:
mov rax, 1 ; syscall number, 1 = write
mov rdi, 1 ; file descriptor, 1 = stdout
mov rsi, nl ; pointer to data
mov rdx, 1 ; size of the data
syscall
ret
print_fizz:
mov rax, 1 ; syscall number, 1 = write
mov rdi, 1 ; file descriptor, 1 = stdout
mov rsi, fizz ; pointer to data
mov rdx, fizz_len ; size of the data
syscall
ret
print_buzz:
mov rax, 1 ; syscall number, 1 = write
mov rdi, 1 ; file descriptor, 1 = stdout
mov rsi, buzz ; pointer to data
mov rdx, buzz_len ; size of the data
syscall
ret
; gets number to print through rdi
; this function won't print anything if number is 0
; but we will never try to print zero anyway
print_number:
; local variables:
sub rsp, 24 ; the string [rsp + 16 + index]
push 0 ; length of the string [rsp + 8]
push qword rdi ; current number [rsp]
; we will be filling the string with ascii digits from back
pn_loop_body:
cmp qword [rsp], 0
je pn_after_loop
mov rdx, 0 ; clear remainder
mov rax, qword [rsp] ; divided
mov rcx, qword 10 ; divisor
div rcx ; result is in rax, remainder is in rdx
mov [rsp], rax ; put result back into current number
add rdx, 48 ; add 48 to remainder to get ascii code
inc qword [rsp + 8] ; increment the length
lea rbx, [rsp + 16 + 24] ; store pointer to end of string in rbx
sub rbx, [rsp + 8] ; subtruct length of string to get pointer to beginning
mov [rbx], dl ; put the ascii character in its place
jmp pn_loop_body
pn_after_loop:
lea rbx, [rsp + 16 + 24] ; store pointer to end of string in rbx
sub rbx, [rsp + 8] ; subtruct length of string to get pointer to beginning
mov rax, 1 ; syscall number, 1 = write
mov rdi, 1 ; file descriptor, 1 = stdout
mov rsi, rbx ; pointer to data
mov rdx, [rsp + 8] ; size of the data
syscall
; deallocate local variables
add rsp, 8 + 8 + 24 ; remove number, length, and string
ret