mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-23 07:28:04 +08:00
added fizzbuzz chapter
This commit is contained in:
parent
94220f9837
commit
9c8ca24a6c
4 changed files with 111 additions and 55 deletions
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
|
@ -10,6 +10,8 @@
|
||||||
"iostream",
|
"iostream",
|
||||||
"memcpy",
|
"memcpy",
|
||||||
"pseudocode",
|
"pseudocode",
|
||||||
|
"stringstream",
|
||||||
|
"strncpy",
|
||||||
"struct",
|
"struct",
|
||||||
"structs"
|
"structs"
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ the 64 bit ARM Instruction Set Architecture (ISA).
|
||||||
| 5 | [Interlude - Load and Store](./section_1/regs/ldr.md) |
|
| 5 | [Interlude - Load and Store](./section_1/regs/ldr.md) |
|
||||||
| 6 | [Calling and Returning From Functions](./section_1/funcs/README.md) |
|
| 6 | [Calling and Returning From Functions](./section_1/funcs/README.md) |
|
||||||
| 7 | [Passing Parameters To Functions](./section_1/funcs/README2.md) |
|
| 7 | [Passing Parameters To Functions](./section_1/funcs/README2.md) |
|
||||||
|
| 8 | [FizzBuzz - a Complete Program](./section_1/fizzbuzz/README.md) |
|
||||||
|
|
||||||
## Section 2 - Stuff
|
## Section 2 - Stuff
|
||||||
|
|
||||||
|
|
|
||||||
51
section_1/fizzbuzz/README.md
Normal file
51
section_1/fizzbuzz/README.md
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Section 1 / Chapter 8 / FizzBuzz
|
||||||
|
|
||||||
|
In this chapter we build the classic tech interview question: FizzBuzz.
|
||||||
|
|
||||||
|
The idea is simple. Write a program that enumerates the integers from 0 to some stopping value, perhaps 100.
|
||||||
|
|
||||||
|
For each integer:
|
||||||
|
|
||||||
|
* If it is a multiple of 3, print Fizz
|
||||||
|
|
||||||
|
* If it is a multiple of 5, print Buzz
|
||||||
|
|
||||||
|
* If it is a multiple of both 3 *and* 5, print FizzBuzz
|
||||||
|
|
||||||
|
* Otherwise, if none of the above applies, print the integer.
|
||||||
|
|
||||||
|
The interviewer's hope is that you get twisted in knots trying
|
||||||
|
to navigate the case where the integer is a multiple of both 3 and
|
||||||
|
5. There are many ways to solve this challenge.
|
||||||
|
|
||||||
|
One way might be to test for being a multiple of 15 *first* and print
|
||||||
|
FizzBuzz if true. Then test against 3 and then against 5.
|
||||||
|
|
||||||
|
Another way is to accumulate the correct out by testing against 3 and
|
||||||
|
adding Fizz to a buffer. Then test against 5 and if appropriate append
|
||||||
|
Buzz to the buffer. Either the buffer was empty, in which case you get
|
||||||
|
Buzz alone - or it already contained Fizz in which case the buffer now
|
||||||
|
contains FizzBuzz. Finally, if *anything* is in the buffer, cause the
|
||||||
|
buffer to be printed and append a new line.
|
||||||
|
|
||||||
|
In C++, the buffer could be a C++ string or a stringstream. In C
|
||||||
|
you might think that you must resort to using an array of `char` to
|
||||||
|
act as the buffer, filling it with `strncpy` or some such nonsense.
|
||||||
|
|
||||||
|
But you don't have to bother! `printf` is a buffered output stream.
|
||||||
|
It won't print anything until it encounters a new line character.
|
||||||
|
|
||||||
|
In this program, we'll use this to buffer up either Fizz, Buzz or
|
||||||
|
both then as indicated above, we'll end with a new line and BAM -
|
||||||
|
whatever was in the `printf` buffer gets sent to the console.
|
||||||
|
|
||||||
|
[Here is a video](https://youtu.be/aJSGTIxu4ik) where we walk through
|
||||||
|
the process of writing FizzBuzz from scratch in ARM 64 bit assembly
|
||||||
|
language.
|
||||||
|
|
||||||
|
[Here is the source code](./fizzbuzz.s).
|
||||||
|
|
||||||
|
The video is long but there is much benefit to be had by watching
|
||||||
|
and listening to another person's process as they write the code.
|
||||||
|
**AND especially** listening and watching to them debug when
|
||||||
|
things go wrong!
|
||||||
|
|
@ -1,91 +1,93 @@
|
||||||
/* Perry Kivolowitz
|
.global main
|
||||||
CSC3510
|
.text
|
||||||
*/
|
.align 2
|
||||||
.global main
|
|
||||||
.text
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
/* FizzBuzz - a classic interview question.
|
/* FizzBuzz - a classic interview question.
|
||||||
|
|
||||||
Count from 0 to n (let's make it 100).
|
Count from 0 to n (let's make it 100).
|
||||||
If the value is divisible by 3, print Fizz
|
If the value is divisible by 3, print Fizz
|
||||||
If the value is divisible by 5, print Buzz
|
If the value is divisible by 5, print Buzz
|
||||||
If the value is divisible by both 3 and 5, print FizzBuzz
|
If the value is divisible by both 3 and 5, print FizzBuzz
|
||||||
Otherwise, print the number.
|
Otherwise, print the number.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Bible:
|
/* Bible:
|
||||||
|
|
||||||
x20 counter
|
x20 counter
|
||||||
w21 bool that says whether or not I have printed anything
|
w21 bool that says whether or not I have printed anything
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* mod(a, b) - implements a % b
|
/* mod(a, b) - implements a % b
|
||||||
integer divide a by b - for example - 5 % 3 would need 5 // 3 yielding 1
|
a comes to us in x0
|
||||||
multiply result by b - 1 * 3 is 3
|
b comes to us in x1
|
||||||
subtract result from a - 5 - 3 yielding 2 and that's our return value.
|
method:
|
||||||
|
integer divide a by b - for example - 5 % 3
|
||||||
|
would need 5 // 3 yielding 1
|
||||||
|
multiply result by b - 1 * 3 is 3
|
||||||
|
subtract result from a - 5 - 3 yielding 2
|
||||||
|
and that's our return value.
|
||||||
*/
|
*/
|
||||||
mod: sdiv x2, x0, x1 // x2 gets a // b
|
mod: sdiv x2, x0, x1 // x2 gets a // b
|
||||||
msub x0, x2, x1, x0 // x0 gets a - a // b * b
|
msub x0, x2, x1, x0 // x0 gets a - a // b * b
|
||||||
ret
|
ret
|
||||||
|
|
||||||
main: stp x20, x30, [sp, -16]!
|
main: stp x20, x30, [sp, -16]!
|
||||||
str x21, [sp, -16]!
|
str x21, [sp, -16]!
|
||||||
|
|
||||||
mov x20, xzr
|
mov x20, xzr
|
||||||
1: cmp x20, 100
|
1: cmp x20, 100
|
||||||
bge 99f
|
bge 99f
|
||||||
|
|
||||||
mov w21, wzr
|
mov w21, wzr
|
||||||
|
|
||||||
// Test for divisible by 3
|
// Test for divisible by 3
|
||||||
mov x0, x20
|
mov x0, x20
|
||||||
mov x1, 3
|
mov x1, 3
|
||||||
bl mod
|
bl mod
|
||||||
cbnz x0, 5f
|
cbnz x0, 5f
|
||||||
// If we get here, the counter was divisible by 3
|
// If we get here, the counter was divisible by 3
|
||||||
ldr x0, =fizz
|
ldr x0, =fizz
|
||||||
bl printf
|
bl printf
|
||||||
add w21, w21, 1
|
add w21, w21, 1
|
||||||
|
|
||||||
5: mov x0, x20
|
5: mov x0, x20
|
||||||
mov x1, 5
|
mov x1, 5
|
||||||
bl mod
|
bl mod
|
||||||
cbnz x0, 10f
|
cbnz x0, 10f
|
||||||
// If we get here, the counter was divisible by 5
|
// If we get here, the counter was divisible by 5
|
||||||
ldr x0, =buzz
|
ldr x0, =buzz
|
||||||
bl printf
|
bl printf
|
||||||
add w21, w21, 1
|
add w21, w21, 1
|
||||||
|
|
||||||
10: cbz w21, 20f
|
10: cbz w21, 20f
|
||||||
// If we get here, it means that we have printed
|
// If we get here, it means that we have printed
|
||||||
// something (either fizz, or buzz or fizzbuzz)
|
// something (either fizz, or buzz or fizzbuzz)
|
||||||
// so all we need now is a new line
|
// so all we need now is a new line
|
||||||
ldr x0, =nl
|
ldr x0, =nl
|
||||||
bl puts
|
bl puts
|
||||||
b 80f
|
b 80f
|
||||||
|
|
||||||
20: // If we get here, the counter was neither a
|
20: // If we get here, the counter was neither a
|
||||||
// multiple of 3 nor of 5. Therefore, we need
|
// multiple of 3 nor of 5. Therefore, we need
|
||||||
// to print the counter itself.
|
// to print the counter itself.
|
||||||
|
|
||||||
ldr x0, =fmt
|
ldr x0, =fmt
|
||||||
mov x1, x20
|
mov x1, x20
|
||||||
bl printf
|
bl printf
|
||||||
|
|
||||||
80: add x20, x20, 1
|
80: add x20, x20, 1
|
||||||
b 1b
|
b 1b
|
||||||
|
|
||||||
|
|
||||||
99: ldr x21, [sp], 16
|
99: ldr x21, [sp], 16
|
||||||
ldp x20, x30, [sp], 16
|
ldp x20, x30, [sp], 16
|
||||||
mov w0, wzr
|
mov w0, wzr
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.data
|
.data
|
||||||
fizz: .asciz "Fizz"
|
fizz: .asciz "Fizz"
|
||||||
buzz: .asciz "Buzz"
|
buzz: .asciz "Buzz"
|
||||||
nl: .asciz ""
|
nl: .asciz ""
|
||||||
fmt: .asciz "%ld\n"
|
fmt: .asciz "%ld\n"
|
||||||
|
|
||||||
.end
|
.end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue