===================== Quiz 9: Caesar cipher [TOC] ===================== Write a program in assembly that behaves as follows: - The user can type in some message on _stdin (standard input)_ and can terminate the message with the _end of file_ condition (Control-D). - The program reprints the message character by character. Like the `cat` program. However, the characters `a`, .., `y`, `z` are replaced with `b`, ..., `z`, `a`. That means the characters `a` to `y` are replaced with the next character in the alphabet, and `z` is replaced with `a`. All other characters (e.g. upper case characters and punctuators) are reprinted unchanged. Take advantage of the fact the in the __ASCII table__ the characters `a`, .., `z` come in alphabetical order. With some Unix magic you also can write a message first into a file: ---- CODE (file=session09/caesar/msg) ------------------------------------------ abcdefghijklmnopqrstuvwxz Hallo, Welt! hello, world! -------------------------------------------------------------------------------- and then redirect the file to stdin: ---- SHELL (path=session09/caesar/, hide) -------------------------------------- make 1_ulm_build/caesar/ulmas 0_ulm_variants/hello/caesar.s -------------------------------------------------------------------------------- ---- SHELL (path=session09/caesar/) -------------------------------------------- 1_ulm_build/caesar/ulm a.out < msg -------------------------------------------------------------------------------- Required Instructions ===================== Use the table for __Ordered Relations__ (Session 5, Page 3) to provide the following instructions for conditional jumps: - _ja (jump above)_ with opcode $0\text{x}0C$. It can be used to branch if $u(a) > u(b)$. The branch condition therefore is that a previous subtraction $u(a) - u(b)$ was negative. Example usage: ---- CODE (type=s) ----------------------------------------------------------- getc %1 # read character (its ASCII code) from stdin subq 'z', %1, %0 # compute: %1 - 'z' -> %0 ja not_in_range # jump if char in %1 comes after 'z' in ASCII table ------------------------------------------------------------------------------ - _jb (jump below)_ with opcode $0\text{x}0D$. It can be used to branch if $u(a) < u(b)$. The branch condition therefore is that a previous subtraction $u(a) - u(b)$ was positive. Example usage: ---- CODE (type=s) ----------------------------------------------------------- getc %1 # read character (its ASCII code) from stdin subq 'a', %1, %0 # compute: %1 - 'a' -> %0 jb not_in_range # jump if char in %1 comes before 'a' in ASCII table ------------------------------------------------------------------------------ Together with the instructions from __Page 2__ this is sufficient to realize the program. If you think more instructions are needed or would make it more convenient feel free to add more. Getting Started =============== The right approach would probably be to figure out the perfect algorithm, represent it in a flow-chart and then implement. Here I outline some _hacker's approach_ where you approach the goal step by step. And each step will be expressed with some code that you can use as some kind of pseudo-code (but it actually compiles into an executable and solves some part of the problem). After each step test it. So although you do not come up with the solution in a single step it will be a safe path. First Step ---------- Use the `cat` program. It already does everything, well, except for replacing the characters. In C coode you could express the `cat` program like that: ---- CODE (file=session09/c/caesar0.c) ----------------------------------------- #include int main() { int ch; while ((ch = getchar()) != EOF) { putchar(ch); } } -------------------------------------------------------------------------------- Here the test: ---- SHELL (path=session09/c/) ------------------------------------------------- ucc -o caesar0 caesar0.c caesar0 < ../caesar/msg -------------------------------------------------------------------------------- Second Step ----------- Now modify your assembly program by incrementing the stored ASCII code before you print it. So this replaces _all_ characters with the next character in the ASCII table. So some characters are already replaced correct. ---- CODE (file=session09/c/caesar1.c) ----------------------------------------- #include int main() { int ch; while ((ch = getchar()) != EOF) { ++ch; putchar(ch); } } -------------------------------------------------------------------------------- Here the test (note that the newline also gets replaced): ---- SHELL (path=session09/c/) ------------------------------------------------- ucc -o caesar1 caesar1.c caesar1 < ../caesar/msg -------------------------------------------------------------------------------- Third Step ---------- Only replace characters `a` to `z` with the next character. So except for `z` all characters are replaced correct. ---- CODE (file=session09/c/caesar2.c) ----------------------------------------- #include int main() { int ch; while ((ch = getchar()) != EOF) { if (ch >= 'a' && ch <= 'z') { ++ch; } putchar(ch); } } -------------------------------------------------------------------------------- Here the test (now the newline and punctuators are unchanged): ---- SHELL (path=session09/c/) ------------------------------------------------- ucc -o caesar2 caesar2.c caesar2 < ../caesar/msg -------------------------------------------------------------------------------- Last Step --------- Now deal with the special case that `z` should be replaced with `a`. ---- CODE (file=session09/c/caesar3.c) ----------------------------------------- #include int main() { int ch; while ((ch = getchar()) != EOF) { if (ch == 'z') { ch = 'a'; } else if (ch >= 'a' && ch <= 'z') { ++ch; } putchar(ch); } } -------------------------------------------------------------------------------- Here the test: ---- SHELL (path=session09/c/) ------------------------------------------------- ucc -o caesar3 caesar3.c caesar3 < ../caesar/msg -------------------------------------------------------------------------------- Now, it is a matter of taste to replace `ch <= 'z'` with `ch < 'z'` ... Submission for Quiz 8 ===================== Submit your description of the instruction set `isa.txt` and your program `caesar.s` with `submit hpc quiz08 isa.txt caesar.s`. :links: ASCII table -> https://en.wikipedia.org/wiki/ASCII Ordered Relations -> doc:session05/page03 Page 2 -> doc:session09/page02