Skip to main content
\(\newcommand{\doubler}[1]{2#1} \newcommand{\binary}{\mathtt} \newcommand{\hex}{\mathtt} \newcommand{\octal}{\mathtt} \newcommand{\prog}{\mathtt} \newcommand{\lt}{<} \newcommand{\gt}{>} \newcommand{\amp}{&} \)

AppendixBSolutions to Selected Exercises

Exercises2.2Exercises

Exercise1
Answer

  1. \(\hex{4567}\)

  2. \(\hex{89ab}\)

  3. \(\hex{fedc}\)

  4. \(\hex{0252}\)

Exercise2
Answer

  1. \(\binary{1000} \; \binary{0011} \; \binary{1010} \; \binary{1111}\)

  2. \(\binary{1001} \; \binary{0000} \; \binary{0000} \; \binary{0001}\)

  3. \(\binary{1010} \; \binary{1010} \; \binary{1010} \; \binary{1010}\)

  4. \(\binary{0101} \; \binary{0101} \; \binary{0101} \; \binary{0101}\)

Exercise3
Answer

  1. \(32\)

  2. \(48\)

  3. \(4\)

  4. \(16\)

Exercise4
Answer

  1. \(2\)

  2. \(8\)

  3. \(16\)

  4. \(3\)

  5. \(5\)

  6. \(2\)

Exercises2.4Exercises

Exercise1
Answer

Decimal number: \(r = 10, n = 8, d_{7} = 2, d_{6} = 9, d_{5} = 4, d_{4} = 5, d_{3} = 8, d_{2} = 2, d_{1} = 5, d_{0} = 4\)

Hexadecimal number: \(r = 16, n = 8, d_{7} = 2, d_{6} = 9, d_{5} = 4, d_{4} = 5, d_{3} = 8, d_{2} = 2, d_{1} = 5, d_{0} = 4\)

Exercise2
Answer

\begin{align*} \binary{1010} \; \binary{0101}_{2} &= 1 \times 2^{7} + 0 \times 2^{6} + 1 \times 2^{5} + 0 \times 2^{4} + 0 \times 2^{3} + 1 \times 2^{2} + 0 \times 2^{1} + 1 \times 2^{0}\\ &= 128 + 0 + 32 + 0 + 0 + 4 + 0 + 1 \\ &= 165_{10} \end{align*}
Exercise3
Answer

  1. \(170\)

  2. \(85\)

  3. \(240\)

  4. \(15\)

  5. \(128\)

  6. \(99\)

  7. \(123\)

  8. \(255\)

Exercise4
Answer

  1. \(43981\)

  2. \(4660\)

  3. \(65244\)

  4. \(2015\)

  5. \(32768\)

  6. \(1024\)

  7. \(32170\)

  8. \(12345\)

Exercise5
Answer

  1. Set \(Result = 0\)

  2. For \(i = 0, \cdots, (n-1)\)

    • \(Result = Result + d_{i} * 16^{i}\)

  1. \(40960\)

  2. \(65535\)

  3. \(1024\)

  4. \(4369\)

  5. \(34952\)

  6. \(400\)

  7. \(43981\)

  8. \(21845\)

Exercises2.6Exercises

Exercise1
Answer

\(\binary{1111011} = \hex{7d}\)

Exercise2
Answer

  1. \(\hex{64}\)

  2. \(\hex{7d}\)

  3. \(\hex{0a}\)

  4. \(\hex{58}\)

  5. \(\hex{ff}\)

  6. \(\hex{10}\)

  7. \(\hex{20}\)

  8. \(\hex{80}\)

Exercise3
Answer

  1. \(\hex{0400}\)

  2. \(\hex{03e8}\)

  3. \(\hex{8000}\)

  4. \(\hex{7fff}\)

  5. \(\hex{0100}\)

  6. \(\hex{ffff}\)

  7. \(\hex{1234}\)

  8. \(\hex{abcd}\)

Exercise4
Answer

Since there are 12 values, we need 4 bits. Any 4-bit code would work. Here is one example:

Grade Code (in hex)
A \(\binary{0000}\) \(\hex{0}\)
A- \(\binary{0001}\) \(\hex{1}\)
B+ \(\binary{0010}\) \(\hex{2}\)
B \(\binary{0011}\) \(\hex{3}\)
B- \(\binary{0100}\) \(\hex{4}\)
C+ \(\binary{0101}\) \(\hex{5}\)
C \(\binary{0110}\) \(\hex{6}\)
C- \(\binary{0111}\) \(\hex{7}\)
D+ \(\binary{1000}\) \(\hex{8}\)
D \(\binary{1001}\) \(\hex{9}\)
D- \(\binary{1010}\) \(\hex{a}\)
F \(\binary{1011}\) \(\hex{b}\)

Exercises2.8Exercises

Exercise1
Answer

Four bytes are sufficient to store an unsigned integer up to \(4,294,967,295\) so we would need to allocate the memory bytes at \(\hex{2fffeb96}\text{,}\) \(\hex{2fffeb97}\text{,}\) \(\hex{2fffeb98}\text{,}\) and \(\hex{2fffeb99}\text{.}\)

Exercise2
Answer
\(\hex{00100e}\text{:}\) \(\hex{00}\)
\(\hex{00100f}\text{:}\) \(\hex{01}\)
\(\hex{001010}\text{:}\) \(\hex{02}\)
\(\hex{001011}\text{:}\) \(\hex{03}\)
\(\cdots\) \(\cdots\)
\(\hex{00102a}\text{:}\) \(\hex{1c}\)
\(\hex{00102b}\text{:}\) \(\hex{1d}\)
Exercise3
Answer

\(\hex{10}_{16}\text{,}\) which is 0x10 in C/C++ syntax.

Exercises2.10Programming Exercises

Exercise2
Answer

You can type as many \(\hex{f}\)s as you like, but the program only accepts eight. Therefore, the largest unsigned integer is \(4 \times 8 = 32\) bits.

Exercise3
Solution
printf("%#010x represents the unsigned decimal integer %d\n",
          bitPattern, bitPattern);

Any integer greater than \(\hex{7fffffff}\) gives a negative output. This will be explained in Section 3.4, but for now realize that this change is caused by printf formatting, not the storage format, which is still unsigned int. Also note that we did not change scanf's reading format.

Exercise4
Solution
/* echoDecHexAddr.c
 * Prompts user to enter a number in decimal, another in
 * hexadecimal then echoes both in both bases, also showing
 * where values are stored.
 * 2017-09-29: Bob Plantz
 */

#include <stdio.h>

int main(void)
{
  int x;
  unsigned int y;

  while(1)           // loop "forever"
  {
    printf("Enter a decimal integer (0 to quit): ");
    scanf("%i", &x);
    if (x == 0) break;        // break out of loop

    printf("Enter a bit pattern in hexadecimal: ");
    scanf("%x", &y);
    if (y == 0) break;        // break out of loop

    printf("%i is stored as %#010x at %p, and\n", x, x, &x);
    printf("%#010x represents the decimal integer %d stored at %p\n\n",
	          y, y, &y);
  }
  printf("End of program.\n");

  return 0;
}

Notice the use of an “infinite” loop and a break statement to end a program.

Exercises2.14Programming Exercise

Exercise1
Solution
/* stringInHex.c
 * displays each character in "Hello world" in hex
 * and the address where it is stored.
 *
 * 2017-09-29: Bob Plantz
 */

#include <stdio.h>

int main(void)
{
  char *stringPtr = "Hello world.\n";

  while (*stringPtr != '\0')
  {
    printf("%p:  ", stringPtr);
    printf("0x%02x\n", *stringPtr);
    stringPtr++;
  }
  printf("%p:  ", stringPtr);
  printf("0x%02x\n", *stringPtr);

  return 0;
}

Exercises2.16Programming Exercises

Exercise1
Solution
/* echoString1.c
 * Echoes a string entered by user.
 * 2017-09-29: Bob Plantz
 */

#include <unistd.h>
#include <string.h>

int main(void)
{
  char aString[200];
  char *stringPtr = aString;

  write(STDOUT_FILENO, "Enter a text string: ",
        strlen("Enter a text string: "));  // prompt user

  read(STDIN_FILENO, stringPtr, 1);    // get first character
  while (*stringPtr != '\n')           // look for end of line
  {
    stringPtr++;                       // move to next location
    read(STDIN_FILENO, stringPtr, 1);  // get next character
  }

  // now echo for user
  write(STDOUT_FILENO, "You entered:\n",
        strlen("You entered:\n"));
  stringPtr = aString;
  do
  {
    write(STDOUT_FILENO, stringPtr, 1);
    stringPtr++;
  } while (*stringPtr != '\n');
  write(STDOUT_FILENO, stringPtr, 1);

  return 0;
}
Exercise2
Solution
/* echoString2.c
 * Echoes a string entered by user. Converts input
 * to C-style string.
 * 2017-09-29: Bob Plantz
 */

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main(void)
{
  char aString[200];
  char *stringPtr = aString;

  write(STDOUT_FILENO, "Enter a text string: ",
        strlen("Enter a text string: ")); // prompt user

  read(STDIN_FILENO, stringPtr, 1);    // get first character
  while (*stringPtr != '\n')           // look for end of line
  {
    stringPtr++;                       // move to next location
    read(STDIN_FILENO, stringPtr, 1);  // get next character
  }
  *stringPtr = '\0';                   // make into C string

  // now echo for user
  printf("You entered:\n%s\n", aString);

  return 0;
}
Exercise3
Solution

There are five separate files for this solution. Four of the files, writeStr.h, writeStr.c, readLn.h, and readLn.c, will be used with other programs in the book. If you do not know how to compile multiple-file programs in C, refer to Appendix A.

/* echoString3.c
 * Echoes a string entered by user.
 * 2017-09-29: Bob Plantz
 */

#include "readLn.h"
#include "writeStr.h"
#define STRLEN 5     // limited to 5 for testing readStr
                     // change to 200 for use

int main(void)
{
  char aString[STRLEN];  
  writeStr("Enter a text string: ");
  readLn(aString, STRLEN);
  writeStr("You entered:\n");
  writeStr(aString);
  writeStr("\n");

  return 0;
}
/* writeStr.h
 * Writes a line to standard out.
 *
 * input:
 *    pointer to C-style text string
 * output:
 *    to screen
 *    returns number of chars written
 *
 * 2017-09-29: Bob Plantz
 */
 
#ifndef WRITESTR_H
#define WRITESTR_H
int writeStr(char *);
#endif
/* writeStr.c
 * Writes a line to standard out.
 *
 * input:
 *    pointer to C-style text string
 * output:
 *    to screen
 *    returns number of chars written
 *
 * 2017-09-29: Bob Plantz
 */

#include <unistd.h>
#include "writeStr.h"

int writeStr(char *stringAddr)
{
  int count = 0;

  while (*stringAddr != '\0')
  {
    write(STDOUT_FILENO, stringAddr, 1);
    count++;
    stringAddr++;
  }

  return count;
}
/* readLn.h
 * Reads a line from standard in.
 * Drops newline character. Eliminates 
 * excess characters from input buffer.
 *
 * input:
 *    from keyboard
 * output:
 *    null-terminated text string
 *    returns number of chars in text string
 *
 * 2017-09-29: Bob Plantz
 */
 
#ifndef READLN_H
#define READLN_H
int readLn(char *, int);
#endif
/* readLn.c
 * Reads a line from standard in.
 * Drops newline character. Eliminates 
 * excess characters from input buffer.
 *
 * input:
 *    from keyboard
 * output:
 *    null-terminated text string
 *    returns number of chars in text string
 *
 * 2017-09-29: Bob Plantz
 */

#include <unistd.h>
#include "readLn.h"

int readLn(char *stringAddr, int maxLength)
{
  int count = 0;
  maxLength--;          // allow space for NUL
  read(STDIN_FILENO, stringAddr, 1);
  while (*stringAddr != '\n')
  {
    if (count < maxLength)
    {
      count++;
      stringAddr++;
    }
    read(STDIN_FILENO, stringAddr, 1);
  }
  *stringAddr = '\0';   // terminate C string
   
  return count;
}

Exercises3.2Exercises

Exercise1
Answer

Four bits. Note that six of the bit patterns are unused.

Exercise2
Solution

  • \(carry_{0} = 0\)

  • For \(i = 0, \cdots, (N-1)\)

    • sum\(_{i} = (x_{i} + y_{i} + carry_{i})\) % \(2\)

    • carry\(_{i+1} = (x_{i} + y_{i} + carry_{i}) / 2\)

Exercise3
Solution

  • \(carry_{0} = 0\)

  • For \(i = 0, \cdots, (N-1)\)

    • sum\(_{i} = (x_{i} + y_{i} + carry_{i})\) % \(16\)

    • carry\(_{i+1} = (x_{i} + y_{i} + carry_{i}) / 16\)

Exercise4
Solution

Using the bit patterns in Table 3.1.3, we could store one decimal digit in every four bits. That is, the lowest-order digit would be stored in bits 3–0, the next lower-order digit in bits 7–4, etc. For example, let's consider \(48 + 27\text{:}\)

\(48_{10}\) \(\rightarrow\) \(\hex{00000048}_{16}\)
+ \(27_{10}\) \(\rightarrow\) \(\hex{00000027}_{16}\)
\(75_{10}\) \(\ne\) \(\hex{0000007f}_{16}\)

Do Exercise 3.2.3 before performing the addition in hexadecimal.

Exercise5
Solution

Subtracting \(y\) from \(x\text{.}\)

  • \(borrow = 0\)

  • For \(i = 0, \cdots, (N-1)\)

    • If \(y_{i} \le x_{i}\)

      • difference\(_{i} = x_{i} - y_{i}\)

    • Else

      • \(j = i + 1\)

      • While \((x_{j} = 0)\) and \((j \lt N)\)

        • \(j = j + 1\)

      • If \(j = N\)

        • \(borrow = 1\)

        • \(j = j - 1\)

        • \(x_{j} = x_{j} + 2\)

    • While \(j \gt i\)

      • \(x_{j} = x_{j} - 1 \)

      • \(j = j - 1\)

      • \(x_{j} = x_{j} + 2\)

    • difference\(_{i} = x_{i} - y_{i}\)

Exercise6
Solution

Subtracting \(y\) from \(x\text{.}\)

  • \(borrow = 0\)

  • For \(i = 0, \cdots, (N-1)\)

    • If \(y_{i} \le x_{i}\)

      • difference\(_{i} = x_{i} - y_{i}\)

    • Else

      • \(j = i + 1\)

      • While \((x_{j} = 0)\) and \((j \lt N)\)

        • \(j = j + 1\)

      • If \(j = N\)

        • \(borrow = 1\)

        • \(j = j - 1\)

        • \(x_{j} = x_{j} + 16\)

    • While \(j \gt i\)

      • \(x_{j} = x_{j} - 1 \)

      • \(j = j - 1\)

      • \(x_{j} = x_{j} + 16\)

    • difference\(_{i} = x_{i} - y_{i}\)

Exercises3.5Exercises

Exercise1
Solution

  • If \(x \ge 0\)

    • Convert \(x\) to binary.

  • Else

    • Negate \(x\)

    • Convert the result to binary.

    • Compute the 2's complement of the result in the binary domain.

Exercise2
Solution

  • If high-oder bit is \(0\)

    • Convert \(x\) to decimal.

  • Else

    • Compute the 2's complement of \(x\text{.}\)

    • Compute the decimal equivalent of the result.

    • Place a minus sign in front of the decimal equivalent.

Exercise3
Answer

  1. \(+85\)

  2. \(-85\)

  3. \(-16\)

  4. \(+15\)

  5. \(-128\)

  6. \(+99\)

  7. \(+123\)

Exercise4
Answer

  1. \(+4660\)

  2. \(-30875\)

  3. \(+22136\)

  4. \(-4660\)

  5. \(-292\)

  6. \(+2016\)

  7. \(-32768\)

  8. \(+32767\)

  9. \(-32767\)

Exercise5
Answer

  1. \(\hex{64}\)

  2. \(\hex{ff}\)

  3. \(\hex{f6}\)

  4. \(\hex{58}\)

  5. \(\hex{81}\)

  6. \(\hex{f0}\)

  7. \(\hex{e0}\)

  8. \(\hex{80}\)

Exercise6
Answer

  1. \(\hex{7bcd}\)

  2. \(\hex{ff04}\)

  3. \(\hex{0400}\)

  4. \(\hex{fc00}\)

  5. \(\hex{ffff}\)

  6. \(\hex{8000}\)

  7. \(\hex{7fff}\)

  8. \(\hex{ff00}\)

  9. \(\hex{8001}\)

  10. \(\hex{ff80}\)

Exercises3.7Exercises

Exercise1
Answer

  1. Start at the tic mark for \(1\text{,}\) move \(3\) tic marks CW, giving \(4 = \binary{100}_{2}\text{.}\) We did not pass the tic mark at the top, so C = \(\binary{0}\text{,}\) and the result is correct.

  2. Start at the tic mark for \(3\text{,}\) move \(4\) tic marks CW, giving \(7 = \binary{111}_{2}\text{.}\) We did not pass the tic mark at the top, so C = \(\binary{0}\text{,}\) and the result is correct.

  3. Start at the tic mark for \(5\text{,}\) move \(6\) tic marks CW, giving \(3 = \binary{011}_{2}\text{.}\) We passed the tic mark at the top, so C = \(\binary{1}\text{,}\) and the result is wrong.

  4. Start at the tic mark for \(+1\text{,}\) move \(3\) tic marks CW, giving \(-4 = \binary{100}_{2}\text{.}\) We passed the tic mark at the bottom, so V = \(\binary{1}\text{,}\) and the result is wrong.

  5. Start at the tic mark for \(-3\text{,}\) move \(3\) tic marks CCW, giving \(+2 = \binary{010}_{2}\text{.}\) We passed the tic mark at the bottom, so C = \(\binary{0}\text{,}\) and the result is wrong.

  6. Start at the tic mark for \(+3\text{,}\) move \(4\) tic marks CCW, giving \(-1 = \binary{111}_{2}\text{.}\) We did not pass the tic mark at the bottom, so C = \(\binary{0}\text{,}\) and the result is correct.

Exercise2
Answer
sum signed unsigned
a. \(\hex{ff}\) right right
b. \(\hex{45}\) right wrong
c. \(\hex{fb}\) right right
sum signed unsigned
d. \(\hex{de}\) wrong right
e. \(\hex{0e}\) right wrong
f. \(\hex{00}\) wrong wrong
Exercise3
Answer
sum signed unsigned
a. \(\hex{0000}\) right wrong
b. \(\hex{1110}\) right wrong
c. \(\hex{0000}\) wrong wrong
sum signed unsigned
d. \(\hex{03ff}\) right wrong
e. \(\hex{7fff}\) right right
f. \(\hex{7fff}\) wrong wrong

Exercises4.3Programming Exercise

Exercise1
Answer

Shifting \(17\) to the left \(14\) times gives \(278528\text{.}\) Shifting \(17\) to the right \(3\) times gives \(2\text{.}\)

Exercises4.5Programming Exercise

Exercise1
Solution
/* convertHex.c
 * Asks user to enter a number in hexadecimal
 * then echoes it in hexadecimal and in decimal.
 * Assumes that user does not make mistakes.
 * 2017-09-29: Bob Plantz
 */

#include <stdio.h>
#include <unistd.h>

int main(void)
{
  int x;
  unsigned char aChar;

  printf("Enter an integer in hexadecimal: ");
  fflush(stdout);

  x = 0;                          // initialize result
  read(STDIN_FILENO, &aChar, 1);  // get first character
  while (aChar != '\n') {        // look for return key
    x = x << 4;                   // make room for next four bits
    if (aChar > '9') {
      aChar = aChar + 9;          // for 'gap' in hex
    }
    aChar = aChar & 0x0f;         // mask off ascii part
    x = x + (int)aChar;           // insert in vacant space
    read(STDIN_FILENO, &aChar, 1);
  }
   
  printf("You entered %#010x = %d (decimal)\n\n", x, x);

  return 0;
}

The fflush(stdout); statement is required because output to stdout is line buffered.

Exercises5.2Exercises

Exercise1
Solution

For Equation (5.1.3):

\(x\) \(x \cdot 1\)
\(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{1}\)

And for Equation (5.1.4):

\(x\) \(x + 0\)
\(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{1}\)
Exercise2
Solution

For Equation (5.1.5):

\(x\) \(y\) \(x \cdot y\) \(y \cdot x\)
\(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)

And for Equation (5.1.6):

\(x\) \(y\) \(x + y\) \(y + x\)
\(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)
Exercise3
Solution

For Equation (5.1.7):

\(x\) \(x \cdot 0\)
\(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{0}\)

And for Equation (5.1.8):

\(x\) \(x + 1\)
\(\binary{0}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{1}\)
Exercise4
Solution

For Equation (5.1.9):

\(x\) \(x'\) \(x \cdot x'\)
\(\binary{0}\) \(\binary{1}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{0}\)

And for Equation (5.1.10):

\(x\) \(x'\) \(x + x'\)
\(\binary{0}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{1}\)
Exercise5
Solution

For Equation (5.1.11):

\(x\) \(x\) \(x \cdot x\)
\(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{1}\)

And for Equation (5.1.12):

\(x\) \(x\) \(x + x\)
\(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{1}\)
Exercise6
Solution

For Equation (5.1.13):

\(x\) \(y\) \(z\) \(y + z\) \(x \cdot (y + z)\) \(x \cdot y\) \(x \cdot z\) \(x \cdot y + x \cdot z\)
\(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{1}\) \(\binary{0}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{0}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)

And for Equation (5.1.14):

\(x\) \(y\) \(z\) \(y \cdot z\) \(x + y \cdot z\) \(x + y\) \(x + z\) \((x + y) \cdot (x + z)\)
\(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{0}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{1}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{1}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{1}\)

Exercises5.4Exercise

Exercise1
Solution

The \(\sum\) column shows where the sum of minterms evaluates to \(1\text{,}\) and the \(\prod\) column shows where the product of maxterms evaluates to \(0\text{.}\) Of course, in the blank cells the functions evaluate to the complementary value.

\(x\) \(y\) \(z\) \(F(x,y,z) = \sum(0,1,5,6)\) \(F(x,y,z) = \prod(2,3,4,7)\)
\(\binary{0}\) \(\binary{0}\) \(\binary{0}\) \(\binary{1}\)
\(\binary{0}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{0}\) \(\binary{1}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{0}\) \(\binary{1}\) \(\binary{1}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{0}\) \(\binary{0}\)
\(\binary{1}\) \(\binary{0}\) \(\binary{1}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{0}\) \(\binary{1}\)
\(\binary{1}\) \(\binary{1}\) \(\binary{1}\) \(\binary{0}\)

Exercises5.6Exercises

Exercise1
Solution

Let a 4-bit integer be \(wxyz\) where each literal represents one bit. The even 4-bit integers are given by the function:

\begin{alignat*}{1} F(w,x,y,z) \amp {}={} w' \cdot x' \cdot y' \cdot z' + w' \cdot x' \cdot y \cdot z' + w' \cdot x \cdot y' \cdot z' + w' \cdot x \cdot y \cdot z' \\ \amp \quad + w \cdot x' \cdot y' \cdot z' + w \cdot x' \cdot y \cdot z' + w \cdot x \cdot y' \cdot z' + w \cdot x \cdot y \cdot z' \end{alignat*}

Using the distributive property repeatedly we get:

\begin{alignat*}{1} F(w,x,y,z) \amp {}={} z' \cdot (w' \cdot x' \cdot y' + w' \cdot x' \cdot y + w' \cdot x \cdot y' + w' \cdot x \cdot y \\ \amp \quad + w \cdot x' \cdot y' + w \cdot x' \cdot y + w \cdot x \cdot y' + w \cdot x \cdot y) \\ \amp {}={} z' \cdot (w' \cdot (x' \cdot y' + x' \cdot y + x \cdot y' + x \cdot y) \\ \amp \quad + w \cdot (x' \cdot y' + x' \cdot y + x \cdot y' + x \cdot y)) \\ \amp {}={} z' \cdot (w' + w) \cdot (x' \cdot y' + x' \cdot y + x \cdot y' + x \cdot y) \\ \amp {}={} z' \cdot (w'+ w) \cdot (x' \cdot (y' + y) + x \cdot (y' + y)) \\ \amp {}={} z' \cdot (w' + w) \cdot (x' + x) \cdot (y' + y) \end{alignat*}

And from the complement property we arrive at a minimal sum of products:

\begin{gather*} F(w,x,y,z) = z' \end{gather*}

which you recognize as Figure 5.1.3.

Exercise2
Solution

First we draw the Karnaugh map:

<<SVG image is unavailable, or your browser cannot render it>>

Several groupings are possible. Keep in mind that groupings can wrap around. We will work with:

<<SVG image is unavailable, or your browser cannot render it>>

which yields a minimal sum of products:

\begin{equation*} F(x,y,z) = z' + x' \cdot y' + x \cdot y \end{equation*}
Exercise3
Solution

This expression includes maxterms 0, 1, 3, 4, and 7. These appear in a Karnaugh map:

<<SVG image is unavailable, or your browser cannot render it>>

Next we encircle the largest adjacent blocks, where the number of cells in each block is a power of two. Notice that maxterm \(M_{0}\) appears in two groups.

<<SVG image is unavailable, or your browser cannot render it>>

From this Karnaugh map it is very easy to write the function as a minimal product of sums:

\begin{equation*} F(x,y,z) = (x + y) \cdot (y + z) \cdot (y' + z') \end{equation*}
Exercise4
Solution

Using the Karnaugh map zeros:

<<SVG image is unavailable, or your browser cannot render it>>

we obtain the complement of our desired function:

\begin{equation*} F'(x,y,z) = x' \cdot y \cdot z + x \cdot y' \cdot z \end{equation*}

and from DeMorgan's Law:

\begin{equation*} F(x,y,z) = (x + y' + z') \cdot (x' + y + z') \end{equation*}
Exercise5
Answer

<<SVG image is unavailable, or your browser cannot render it>>

Exercise6
Answer

<<SVG image is unavailable, or your browser cannot render it>>

Exercise7
Solution

The prime numbers correspond to the minterms \(m_{2}\text{,}\) \(m_{3}\text{,}\) \(m_{5}\text{,}\) and \(m_{7}\text{.}\) The minterms \(m_{10}\text{,}\) \(m_{11}\text{,}\) \(m_{12}\text{,}\) \(m_{13}\text{,}\) \(m_{14}\text{,}\) \(m_{15}\) cannot occur so are marked “don't care” on the Karnaugh map.

<<SVG image is unavailable, or your browser cannot render it>>

which gives:

\begin{equation*} F(w,x,y,z) = x \cdot z + x' \cdot y \end{equation*}

Exercises6.4Exercise

Exercise1
Solution
\(x_1\) \(x_0\) \(y_1\) \(y_0\) \(F(x,y)\)
\(0\) \(0\) \(0\) \(0\) \(0\)
\(0\) \(0\) \(0\) \(1\) \(1\)
\(0\) \(0\) \(1\) \(0\) \(1\)
\(0\) \(0\) \(1\) \(1\) \(1\)
\(0\) \(1\) \(0\) \(0\) \(0\)
\(0\) \(1\) \(0\) \(1\) \(0\)
\(0\) \(1\) \(1\) \(0\) \(1\)
\(0\) \(1\) \(1\) \(1\) \(1\)
\(1\) \(0\) \(0\) \(0\) \(0\)
\(1\) \(0\) \(0\) \(1\) \(0\)
\(1\) \(0\) \(1\) \(0\) \(0\)
\(1\) \(0\) \(1\) \(1\) \(1\)
\(1\) \(1\) \(0\) \(0\) \(0\)
\(1\) \(1\) \(0\) \(1\) \(0\)
\(1\) \(1\) \(1\) \(0\) \(0\)
\(1\) \(1\) \(1\) \(1\) \(0\)

<<SVG image is unavailable, or your browser cannot render it>>

Exercises8.6Programming Exercises

Exercise1
Answer

This can vary, depending on different versions of the compiler, etc. This is an exercise on using gdb so you can become comfortable with it for when you will actually need it to find your errors. It is also an excellent learning tool.

Exercise2
Answer

The contents of the register should be one less than the integer you entered when the program prompted you. The C statement uses 12 bytes of program memory.

Exercise3
Answer

The program uses the address of ex, &ex, so the variable must be located in memory.

Exercise5
Solution
/* endian.c
 * Determines endianess. If endianess cannot be determined
 * from input value, defaults to "big endian"
 * 2017-09-29: Bob Plantz
 */

#include <stdio.h>

int main(void)
{
  unsigned char *ptr;
  int x, i, bigEndian;

  ptr = (unsigned char *)&x;
   
  printf("Enter a non-zero integer: ");
  scanf("%i", &x);
   
  printf("You entered %#010x and it is stored\n", x);
  for (i = 0; i < 4; i++)
    printf("   %p: %02x\n", ptr + i, *(ptr + i));

  bigEndian = (*ptr == (unsigned char)(0xff & (x >> 24))) &&
            (*(ptr + 1) == (unsigned char)(0xff & (x >> 16))) &&
            (*(ptr + 2) == (unsigned char)(0xff & (x >> 8))) &&
            (*(ptr + 3) == (unsigned char)(0xff & x));
  if (bigEndian)
    printf("which is big endian.\n");
  else
    printf("which is little endian.\n");

  return 0;
}
Exercise6
Solution
/* endianReg.c
 * Stores user int in memory then copies to register var.
 * Use gdb to observe endianess.
 * 2017-09-29: Bob Plantz
 */

#include <stdio.h>

int main(void)
{
  int x;
  register int y;
   
  printf("Enter an integer: ");
  scanf("%i", &x);
   
  y = x;
  printf("You entered %i\n", y);

  return 0;
}

Exercises9.4Programming Exercises

Exercise1
Answer

The exit code is displayed in octal.

Exercise2
Solution
@ f.s
@ Does nothing but return zero to caller.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Program code
        .text
        .align  2
        .global f
        .type   f, %function
f:
        str     fp, [sp, -4]!   @ save caller frame pointer
        add     fp, sp, 0       @ establish our frame pointer

        mov     r0, 0           @ return values go in r0

        sub     sp, fp, 0	      @ delete allocated memory
        ldr     fp, [sp], 4     @ restore caller's frame pointer
        bx      lr              @ back to caller
Exercise3
Solution
@ g.s
@ Returns 123 to caller.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Program code
        .text
        .align  2
        .global g
        .type   g, %function
g:
        str     fp, [sp, -4]!   @ save caller frame pointer
        add     fp, sp, 0       @ establish our frame pointer

        mov     r0, 123         @ return values go in r0

        sub     sp, fp, 0	      @ delete allocated memory
        ldr     fp, [sp], 4     @ restore caller's frame pointer
        bx      lr              @ back to caller
Exercise4
Solution
/* checkRetNos.c
 * calls three assembly language functions and
 * prints their return numbers.
 *
 * 2017-09-29: Bob Plantz
 */

#include <stdio.h>
int positiveNumber(void);
int negativeNumber(void);
int maxNumber(void);

int main()
{
  int x;

  x = positiveNumber();
  printf("Here is a positive constant: %i, ", x);

  x = negativeNumber();
  printf("a negative constant: %i, ", x);

  x = maxNumber();
  printf("and the maximum number: %i.\n", x);

  return 0;
}
@ positiveNumber.s
@ Returns +100 to caller.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Program code
        .text
        .align  2
        .global positiveNumber
        .type   positiveNumber, %function
positiveNumber:
        str     fp, [sp, -4]!   @ save caller frame pointer
        add     fp, sp, 0       @ establish our frame pointer

        mov     r0, 100         @ return +100

        sub     sp, fp, 0	      @ restore stack pointer
        ldr     fp, [sp], 4     @ restore caller's frame pointer
        bx      lr              @ back to caller
@ negativeNumber.s
@ Returns -100 to caller.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Program code
        .text
        .align  2
        .global negativeNumber
        .type   negativeNumber, %function
negativeNumber:
        str     fp, [sp, -4]!   @ save caller frame pointer
        add     fp, sp, 0       @ establish our frame pointer

        mov     r0, -100        @ return -100

        sub     sp, fp, 0	      @ restore stack pointer
        ldr     fp, [sp], 4     @ restore caller's frame pointer
        bx      lr              @ back to caller
@ maxNumber.s
@ Returns the largest "immediate data" constant to caller,
@ which is 8 bits.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Program code
        .text
        .align  2
        .global maxNumber
        .type   maxNumber, %function
maxNumber:
        str     fp, [sp, -4]!   @ save caller frame pointer
        add     fp, sp, 0       @ establish our frame pointer

        mov     r0, 0xff        @ only 8 bits available for immediate

        sub     sp, fp, 0	      @ restore stack pointer
        ldr     fp, [sp], 4     @ restore caller's frame pointer
        bx      lr              @ back to caller
Exercise5
Solution
/*
 * checkRetChars.c
 * calls three assembly language functions and
 * prints their return characters.
 *
 * 2017-09-29: Bob Plantz
 */

#include <stdio.h>
int A(void);
int z(void);
int hashtag(void);

int main()
{
    char aCharacter;

    aCharacter = A();
    printf("Here some characters: %c, ", aCharacter);

    aCharacter = z();
    printf("%c, ", aCharacter);

    aCharacter = hashtag();
    printf("and %c.\n", aCharacter);

    return 0;
}
@ A.s
@ Returns 'A' to caller.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Program code
        .text
        .align  2
        .global A
        .type   A, %function
A:
        str     fp, [sp, -4]!   @ save caller frame pointer
        add     fp, sp, 0       @ establish our frame pointer

        mov     r0, 'A          @ return 'A'

        sub     sp, fp, 0	      @ restore stack pointer
        ldr     fp, [sp], 4     @ restore caller's frame pointer
        bx      lr              @ back to caller
@ z.s
@ Returns 'z' to caller.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Program code
        .text
        .align  2
        .global z
        .type   z, %function
z:
        str     fp, [sp, -4]!   @ save caller frame pointer
        add     fp, sp, 0       @ establish our frame pointer

        mov     r0, 'z          @ return 'z'

        sub     sp, fp, 0	      @ restore stack pointer
        ldr     fp, [sp], 4     @ restore caller's frame pointer
        bx      lr              @ back to caller
@ hashtag.s
@ Returns '#' to caller.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Program code
        .text
        .align  2
        .global hashtag
        .type   hashtag, %function
hashtag:
        str     fp, [sp, -4]!   @ save caller frame pointer
        add     fp, sp, 0       @ establish our frame pointer

        mov     r0, #'#         @ return hashtag

        sub     sp, fp, 0	      @ restore stack pointer
        ldr     fp, [sp], 4     @ restore caller's frame pointer
        bx      lr              @ back to caller

Exercises10.4Programming Exercise

Exercise1
Solution
@ helloBob.s
@ Hello Bob program, in assembly language.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constant
        .equ    STDOUT,1

@ Constant program data
        .section  .rodata
        .align  2
helloMsg:
        .asciz	 "Hello, Bob!\n"
        .equ    helloLngth,.-helloMsg

@ Program code
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer

        mov     r0, STDOUT      @ file number to write to
        ldr     r1, helloMsgAddr   @ pointer to message
        mov     r2, helloLngth  @ number of bytes to write
        bl      write           @ write the message
        
        mov     r0, 0           @ return 0;
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return
        
        .align  2
helloMsgAddr:
        .word   helloMsg

Exercises10.6Programming Exercise

Exercise1
Solution

Experiment with entering different numbers of characters, and you will see that the read function reads the newline character (enter key) as one character. Try entering “abcdls” (without the quotes). Notice that any characters beyond the four requested remain in the input buffer and are read by the shell when the program exits.

@ echo4chars.s
@ Prompts user to enter 4 characters and echoes them
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    STDIN,0
        .equ    STDOUT,1
        .equ    char1,-8
        .equ    char2,-7
        .equ    char3,-6
        .equ    char4,-5
        .equ    nChars,4
        .equ    local,8

@ Constant program data
        .section  .rodata
        .align  2
promptMsg:
        .asciz  "Enter four characters: "
        .equ    promptLngth,.-promptMsg
responseMsg:
        .asciz	"You entered: "
        .equ    responseLngth,.-responseMsg

@ Program code
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        sub     sp, sp, local   @ allocate memory for local var

        mov     r0, STDOUT      @ prompt user for input
        ldr     r1, promptMsgAddr
        mov     r2, promptLngth
        bl      write

        mov     r0, STDIN       @ from keyboard
        add     r1, fp, char1   @ address of 1st char
        mov     r2, 1           @ one char
        bl      read

        mov     r0, STDIN       @ from keyboard
        add     r1, fp, char2   @ address of 2nd char
        mov     r2, 1           @ one char
        bl      read

        mov     r0, STDIN       @ from keyboard
        add     r1, fp, char3   @ address of 3rd char
        mov     r2, 1           @ one char
        bl      read

        mov     r0, STDIN       @ from keyboard
        add     r1, fp, char4   @ address of 4th char
        mov     r2, 1           @ one char
        bl      read

        mov     r0, STDOUT      @ nice message for user
        ldr     r1, responseMsgAddr
        mov     r2, responseLngth
        bl      write

        mov     r0, STDOUT      @ echo user's characters
        add     r1, fp, char1   @ address of 1st char
        mov     r2, nChars      @ all four characters
        bl      write

        mov     r0, 0           @ return 0;
        add     sp, sp, local   @ delete local vars
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return

@ Addresses of messages
        .align  2
promptMsgAddr:
        .word   promptMsg
responseMsgAddr:
        .word   responseMsg

Exercises12.2Programming Exercises

Exercise1
Solution
@ numerals.s
@ Displays the numerals, 0 - 9
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    STDOUT,1
        .equ    numeral,-20
        .equ    local,8

@ Constant program data
        .section .rodata
        .align  2
@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        sub     sp, sp, local   @ allocate memory for local var

        mov     r4, '0          @ numeral 0
loop:
        strb    r4, [fp, numeral]  @ char must be
                                @ in memory for write
        mov     r0, STDOUT      @ write to screen
        add     r1, fp, numeral @ address of numeral
        mov     r2, 1           @ one byte
        bl      write

        add     r4, r4, 1       @ next numeral
        cmp     r4, '9          @ all numerals?
        ble     loop            @ no, keep going

        mov     r0, 0           @ yes, return 0;
        add     sp, sp, local   @ deallocate local var
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return
Exercise2
Solution
@ letters.s
@ Displays the upper case alphabet, A - Z
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    STDOUT,1
        .equ    alpha,-20
        .equ    local,8

@ Constant program data
        .section .rodata
        .align  2
@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        sub     sp, sp, local   @ allocate memory for local var

        mov     r4, 'A          @ beginning of alphabet
loop:
        strb    r4, [fp, alpha] @ char must be
                                @ in memory for write
        mov     r0, STDOUT      @ write to screen
        add     r1, fp, alpha   @ address of alpha
        mov     r2, 1           @ one byte
        bl      write

        add     r4, r4, 1       @ next alpha
        cmp     r4, 'Z          @ whole alphabet?
        ble     loop            @ no, keep going

        mov     r0, 0           @ yes, return 0;
        add     sp, sp, local   @ deallocate local var
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

Exercises12.4Programming Exercise

Exercise1
Solution
@ range3.s
@ Checks if user entered a numeral
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    STDOUT,1
        .equ    STDIN,0
        .equ    NUL,0
        .equ    response,-20
        .equ    local,8

@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz  "Enter a single character: "
        .align  2
numeral:
        .asciz  "You entered a numeral.\n"
        .align  2
other:
        .asciz  "You entered a non-numeric character.\n"
        
@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        sub     sp, sp, local   @ local variable

        ldr     r4, promptAddr  @ prompt user
promptLoop:
        ldrb    r3, [r4]        @ get a char
        cmp     r3, NUL         @ end of string?
        beq     getResponse     @ yes, get response

        mov     r0, STDOUT      @ no, write to screen
        mov     r1, r4          @ address of current char
        mov     r2, 1           @ write 1 byte
        bl      write

        add     r4, r4, 1       @ increment pointer var
        b       promptLoop      @ back to top

getResponse:
        mov     r0, STDIN       @ from keyboard
        add     r1, fp, response   @ address of response
        mov     r2, 2           @ one char plus enter key
        bl      read
        
        ldrb    r3, [fp, response] @ load response
        cmp     r3, '9          @ check high end
        bhi     notNumeral      @ >'9', other char
        cmp     r3, '0          @ check low end
        blo     notNumeral      @ <'0', other char

        ldr     r4, numeralAddr @ "You entered a numeral."
numLoop:
        ldrb    r3, [r4]        @ get a char
        cmp     r3, NUL         @ end of string?
        beq     endThen         @ yes, end of then block
        mov     r0, STDOUT      @ no, write to screen
        mov     r1, r4          @ address of current char
        mov     r2, 1           @ write 1 byte
        bl      write
        add     r4, r4, 1       @ increment pointer var
        b       numLoop         @ back to top
endThen:
        b       endElse         @ branch over else block

notNumeral:
        ldr     r4, otherAddr   @ "You entered some other character."
notNumLoop:
        ldrb    r3, [r4]        @ get a char
        cmp     r3, NUL         @ end of string?
        beq     endElse         @ yes, end of if-else
        mov     r0, STDOUT      @ no, write to screen
        mov     r1, r4          @ address of current char
        mov     r2, 1          @ write 1 byte
        bl      write 
        add     r4, r4, 1       @ increment pointer var
        b       notNumLoop      @ back to top

endElse:
        mov     r0, 0           @ return 0;
        add     sp, sp, local   @ deallocate local var
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

        .align        2
promptAddr:
        .word   prompt
numeralAddr:
        .word   numeral
otherAddr:
        .word   other

Exercises13.3Programming Exercises

Exercise1
Solution

I suggest discussing this with your instructor and colleagues. Opinions will differ. Listen and learn.

Exercise2
Solution
@ writeStr.s
@ Writes a C-style text string to the standard output (screen).
@ Calling sequence:
@       r0 <- address of string to be written
@       bl    writestr
@ returns number of characters written
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    STDOUT,1
        .equ    NUL,0

@ The code
        .text
        .align  2
        .global writeStr
        .type   writeStr, %function
writeStr:
        sub     sp, sp, 16      @ space for saving regs
        str     r4, [sp, 0]     @ save r4
        str     r5, [sp, 4]     @      r5
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer

        mov     r4, r0          @ r4 = string pointer
        mov     r5, 0           @ r5 = count
whileLoop:
        ldrb    r3, [r4]        @ get a char
        cmp     r3, NUL         @ end of string?
        beq     allDone         @ yes, all done

        mov     r0, STDOUT      @ no, write to screen
        mov     r1, r4          @ address of current char
        mov     r2, 1           @ write 1 byte
        bl      write

        add     r4, r4, 1       @ increment pointer var
        add     r5, r5, 1       @ count++
        b       whileLoop       @ back to top
allDone:
        mov     r0, r5          @ return count;
        ldr     r4, [sp, 0]     @ restore r4
        ldr     r5, [sp, 4]     @      r5
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @ restore sp
        bx      lr              @ return
@ helloWorld3.s
@ Hello world program to test writeStr function
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant program data
        .section .rodata
        .align   2
theString:
        .asciz        "Hello World.\n"

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        
        ldr     r0, theStringAddr
        bl      writeStr

        mov     r0, 0           @ return 0;
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return

theStringAddr:
        .word    theString
Exercise3
Solution
@ readLnSimple.s
@ Reads a line (through the '\n') from standard input. Deletes
@ the '\n' and creates a C-style text string.
@ Calling sequence:
@       r0 <- address of place to store string
@       bl    readLn
@ returns number of characters read, excluding NUL.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    STDIN,0
        .equ    NUL,0
        .equ    LF,10     @ '\n' under Linux

@ The code
        .text
        .align  2
        .global readLn
        .type   readLn, %function
readLn:
        sub     sp, sp, 16      @ space for saving regs
        str     r4, [sp, 4]     @ save r4
        str     r5, [sp, 8]     @      r5
        str     fp, [sp, 12]    @      fp
        str     lr, [sp, 16]    @      lr
        add     fp, sp, 12      @ set our frame pointer

        mov     r4, r0          @ r4 = string pointer
        mov     r5, 0           @ r5 = count

        mov     r0, STDIN       @ read from keyboard
        mov     r1, r4          @ address of current storage
        mov     r2, 1           @ read 1 byte
        bl      read
whileLoop:
        ldrb    r3, [r4]        @ get just read char
        cmp     r3, LF          @ end of input?
        beq     endOfString     @ yes, input done
        add     r4, r4, 1       @ no, increment pointer var
        add     r5, r5, 1       @ count++
        mov     r0, STDIN       @ read from keyboard
        mov     r1, r4          @ address of current storage
        mov     r2, #1          @ read 1 byte
        bl      read
        b       whileLoop       @ and check for end
endOfString:
        mov     r0, NUL         @ string terminator
        strb    r0, [r4]        @ write over '\n'
        
        mov     r0, r5          @ return count;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     r5, [sp, 8]     @      r5
        ldr     fp, [sp, 12]    @      fp
        ldr     lr, [sp, 16]    @      lr
        add     sp, sp, 16      @ space for saving regs
        bx      lr              @ return
@ echoString1.s
@ Prompts user to enter a string, then echoes it.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant for assembler
        .equ    nBytes,50  @ amount of memory for string
@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz        "Enter some text: "

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r0, nBytes      @ get memory from heap
        bl      malloc
        mov     r4, r0          @ pointer to new memory

        ldr     r0, promptAddr  @ prompt user
        bl      writeStr
        
        mov     r0, r4          @ get user input
        bl      readLn
        
        mov     r0, r4          @ echo user input
        bl      writeStr
        
        mov     r0, r4          @ free heap memory
        bl      free
        
        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

promptAddr:
        .word    prompt
Exercise4
Solution
@ readLn.s
@ Reads a line (through the '\n') from standard input. Has
@ a size limit. Extra characters and '\n' are ignored. Stores
@ NUL-terminated C string.
@ Calling sequence:
@       r0 <- address of place to store string
@       r1 <- string size limit
@       bl    readLn
@ returns number of characters read, excluding NUL.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    STDIN,0
        .equ    NUL,0
        .equ    LF,10     @ '\n' under Linux

@ The code
        .text
        .align  2
        .global readLn
        .type   readLn, %function
readLn:
        sub     sp, sp, 24      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     r5, [sp, 8]     @      r5
        str     r6, [sp,12]     @      r6
        str     fp, [sp, 16]    @      fp
        str     lr, [sp, 20]    @      lr
        add     fp, sp, 20      @ set our frame pointer

        mov     r4, r0          @ r4 = string pointer
        mov     r5, 0           @ r5 = count
        mov     r6, r1          @ r6 = max chars
        sub     r6, 1           @ for NUL

        mov     r0, STDIN       @ read from keyboard
        mov     r1, r4          @ address of current storage
        mov     r2, 1           @ read 1 byte
        bl      read
whileLoop:
        ldrb    r3, [r4]        @ get just read char
        cmp     r3, LF          @ end of input?
        beq     endOfString     @ yes, input done
        cmp     r5, r6          @ max chars?
        bge     ignore          @ yes, ignore rest
        add     r4, r4, 1       @ no, increment pointer var
        add     r5, r5, 1       @ count++
ignore:
        mov     r0, STDIN       @ read from keyboard
        mov     r1, r4          @ address of current storage
        mov     r2, 1           @ read 1 byte
        bl      read
        b       whileLoop       @ and check for end
endOfString:
        mov     r0, NUL         @ string terminator
        strb    r0, [r4]        @ write over '\n'
        
        mov     r0, r5          @ return count;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     r5, [sp, 8]     @      r5
        ldr     r6, [sp,12]     @      r6
        ldr     fp, [sp, 16]    @      fp
        ldr     lr, [sp, 20]    @      lr
        add     sp, sp, 24      @      sp
        bx      lr              @ return
@ echoString2.s
@ Prompts user to enter a string, then echoes it.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant for assembler
        .equ    nBytes,5  @ amount of memory for string
@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz        "Enter some text: "

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r0, nBytes      @ get memory from heap
        bl      malloc
        mov     r4, r0          @ pointer to new memory

        ldr     r0, promptAddr  @ prompt user
        bl      writeStr
        
        mov     r0, r4          @ get user input
        mov     r1, nBytes      @ limit input size
        bl      readLn
        
        mov     r0, r4          @ echo user input
        bl      writeStr
        
        mov     r0, r4          @ free heap memory
        bl      free
        
        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

promptAddr:
        .word    prompt
Exercise5
Solution

There are multiple ways to solve this problem. I chose to write a separate function, newLine to give good flexibility in how I display text for users. It is a given that users will want you to change your program's display.

@ newLine.s
@ Writes a newline character to the standard output (screen).
@ Calling sequence:
@       bl    newLine
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    STDOUT,1

@ Constant program data
        .section .rodata
        .align   2
theChar:
        .ascii        "\n"

@ The code
        .text
        .align  2
        .global newLine
        .type   newLine, %function
newLine:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer

        mov     r0, STDOUT      @ write to screen
        ldr     r1, theCharAddr @ address of newline char
        mov     r2, 1           @ write 1 byte
        bl      write

        mov     r0, 0           @ return 0;
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return

theCharAddr:
        .word   theChar

Exercises14.2Programming Exercise

Exercise1
Solution
@ lowerCase.s
@ Prompts user to enter alphabetic characters, converts
@ all uppercase to lowercase and shows the result.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant for assembler
        .equ    nBytes,50  @ amount of memory for string
@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz        "Enter some alphabetic characters: "

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r0, nBytes      @ get memory from heap
        bl      malloc
        mov     r4, r0          @ pointer to new memory

        ldr     r0, promptAddr  @ prompt user
        bl      writeStr
        
        mov     r0, r4          @ get user input
        mov     r1, nBytes      @ limit input size
        bl      readLn
       
	mov	r0, r4		@ convert to lowercase
	bl	toLower
 
        mov     r0, r4          @ echo user input
        bl      writeStr
        
        mov     r0, r4          @ free heap memory
        bl      free
        
        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @ restore sp
        bx      lr              @ return

promptAddr:
        .word    prompt
@ toLower.s
@ Converts all alpha characters to lowercase.
@ Calling sequence:
@       r0 <- address of string to be written
@       bl    toLower
@ returns number of characters written
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constants
        .equ    lowerMask,0x20
        .equ    NUL,0

@ The code
        .text
        .align  2
        .global toLower
        .type   toLower, %function
toLower:
        sub     sp, sp, 16      @ space for saving regs
        str     r4, [sp, 0]     @ save r4
        str     r5, [sp, 4]     @      r5
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer

        mov     r4, r0          @ r4 = string pointer
        mov     r5, #0          @ r5 = count
whileLoop:
        ldrb    r3, [r4]        @ get a char
        cmp     r3, NUL         @ end of string?
        beq     allDone         @ yes, all done

        orr     r3, r3, lowerMask  @ convert to lowercase
        strb    r3, [r4]        @ update string

        add     r4, r4, 1       @ increment pointer var
        add     r5, r5, 1       @ count++
        b       whileLoop       @ back to top
allDone:
        mov     r0, r5          @ return count;
        ldr     r4, [sp, 0]     @ restore r4
        ldr     r5, [sp, 4]     @      r5
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @ restore sp
        bx      lr              @ return

Exercises14.4Programming Exercises

Exercise1
Solution

You will need to copy the assembly language code for hexToInt into a file and then assemble it with:


      as --gstabs -o hexToInt2.o hexToInt2.s

Then use gcc to link the object files with the file containing the main function:


      gcc -g -o hexConvert1 hexToInt2.o writeStr.o readLn.o hexConvert1.c
Exercise2
Answer

It works for both cases because all alphabetic characters are numerically higher than the numeral characters in the ASCII code.

Exercise3
Solution
@ hexConvert2.s
@ Prompts user for hex number and converts
@ it to an int.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant for assembler
        .equ    maxChars,9      @ max input chars
        .equ    theString,-16   @ for input string
        .equ    locals,16       @ space for local vars

@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz        "Enter up to 32-bit hex number: "
display:
        .asciz        "The integer is: %i\n"

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        sub     sp, sp, locals  @ for local vars
        
        ldr     r0, promptAddr  @ prompt user
        bl      writeStr
        
        add     r0, fp, theString  @ place for user input
        mov     r1, maxChars    @ limit input size
        bl      readLn
        
        add     r0, fp, theString  @ user input
        bl      hexToInt        @ convert it

        mov     r1, r0          @ result returned in r0
        ldr     r0, displayAddr @ show user the result
        bl      printf          @ from C Standard Lib.
        
        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return

promptAddr:
        .word    prompt
displayAddr:
        .word    display
Exercise4
Solution
@ addHex.s
@ Prompts user for two hex numbers and adds them
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant for assembler
        .equ    maxChars,9      @ max input chars
        .equ    inString1,-24   @ for 1st input string
        .equ    inString2,-36   @ for 2nd input string
        .equ    outString,-52   @ for output string
        .equ    locals,40       @ space for local vars

@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz        "Enter up to 32-bit hex number: "
display:
        .asciz        "Their sum is: "

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
        str     r4, [sp, 0]     @ save r4
        str     r5, [sp, 4]     @      r5
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        sub     sp, sp, locals  @ for local vars
        
        ldr     r0, promptAddr  @ prompt user
        bl      writeStr
        
        add     r0, fp, inString1  @ 1st input
        mov     r1, maxChars    @ limit input size
        bl      readLn
        add     r0, fp, inString1  @ user input
        bl      hexToInt        @ convert it
        mov     r4, r0          @ 1st int

        ldr     r0, promptAddr  @ prompt for 2nd
        bl      writeStr

        add     r0, fp, inString2  @ 2nd input
        mov     r1, maxChars    @ limit input size
        bl      readLn
        add     r0, fp, inString2  @ user input
        bl      hexToInt        @ convert it
        mov     r5, r0          @ 2nd int

        add     r1, r4, r5      @ add the two ints
        add     r0, fp, outString  @ place for result
        bl      intToHex        @ convert to hex string
        
        ldr     r0, displayAddr @ show user result
        bl      writeStr
        
        add     r0, fp, outString
        bl      writeStr
        
        bl      newLine         @ looks nicer
        
        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     r4, [sp, 0]     @ restore r4
        ldr     r5, [sp, 4]     @      r5
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @ restore sp
        bx      lr              @ return

promptAddr:
        .word    prompt
displayAddr:
        .word    display

Exercises14.7Programming Exercises

Exercise1
Solution

The writeStr, readLn, newLine, uDecToInt, and uIntToDec functions have been provided earlier in the book. Here is the main function to solve this problem.

@ incrementDec.s
@ Prompts user for unsigned decimal number and adds 1 to it.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    maxChars,11     @ max input chars
        .equ    inputString,-16 @ for input string
        .equ    outputString,-28 @ for output string
        .equ    locals,32       @ space for local vars

@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz        "Enter an unsigned number up to 4294967294: "

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        sub     sp, sp, locals  @ for local vars
        
        ldr     r0, promptAddr  @ prompt user
        bl      writeStr
        
        add     r0, fp, inputString  @ place for user input
        mov     r1, maxChars    @ limit input size
        bl      readLn
        
        add     r0, fp, inputString  @ user input
        bl      uDecToInt       @ convert it
        
        add     r1, r0, 1       @ increment user's number
        add     r0, fp, outputString
        bl      uIntToDec
        
        add     r0, fp, outputString
        bl      writeStr
        bl      newLine
        
        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return

promptAddr:
        .word    prompt
Exercise2
Solution
@ uIntToDecMls.s
@ Converts an int to the corresponding unsigned
@ decimal text string.
@ Calling sequence:
@       r0 <- address of place to store string
@       r1 <- int to convert
@       bl uIntToDec
@ 2017-09-29: Bob Plantz
@ 2017-09-30: Use mls for remainder comp - Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant for assembler
        .equ    tempString,-40  @ for temp string
        .equ    locals,16       @ space for local vars
        .equ    zero,0x30       @ ascii 0
        .equ    NUL,0

@ The program
        .text
        .align  2
        .global uIntToDec
        .type   uIntToDec, %function
uIntToDec:
        sub     sp, sp, 24      @ space for saving regs
        str     r4, [sp, 0]     @ save r4
        str     r5, [sp, 4]     @      r5
        str     r6, [sp, 8]     @      r6
        str     r7, [sp, 12]    @      r7
        str     fp, [sp, 16]    @      fp
        str     lr, [sp, 20]    @      lr
        add     fp, sp, 20      @ set our frame pointer
        sub     sp, sp, locals @ for local vars
        
        mov     r4, r0          @ caller's string pointer
        add     r5, fp, tempString @ temp string
        mov     r7, 10          @ decimal constant
        
        mov     r0, NUL         @ end of C string
        strb    r0, [r5]
        add     r5, r5, 1       @ move to char storage

        mov     r0, zero        @ assume the int is 0
        strb    r0, [r5]
        movs    r6, r1          @ int to convert
        beq     copyLoop        @ zero is special case
convertLoop:
        cmp     r6, 0           @ end of int?
        beq     copy            @ yes, copy for caller
        udiv    r0, r6, r7      @ no, div to get quotient
        mls     r2, r0, r7, r6  @ the mod (remainder)
        mov     r6, r0          @ the quotient
        orr     r2, r2, zero    @ convert to numeral
        strb    r2, [r5]
        add     r5, r5, 1       @ next char position
        b       convertLoop
copy:
        sub     r5, r5, 1       @ last char stored locally
copyLoop:
        ldrb    r0, [r5]        @ get local char
        strb    r0, [r4]        @ store the char for caller
        cmp     r0, NUL         @ end of local string?
        beq     allDone         @ yes, we're done
        add     r4, r4, 1       @ no, next caller location
        sub     r5, r5, 1       @ next local char
        b       copyLoop
        
allDone:        
        strb    r0, [r4]        @ end C string
        add     sp, sp, locals  @ deallocate local var
        ldr     r4, [sp, 0]     @ restore r4
        ldr     r5, [sp, 4]     @      r5
        ldr     r6, [sp, 8]     @      r6
        ldr     r7, [sp, 12]    @      r7
        ldr     fp, [sp, 16]    @      fp
        ldr     lr, [sp, 20]    @      lr
        add     sp, sp, 24      @      sp
        bx      lr              @ return
Exercise3
Solution
@ incrementSigned.s
@ Prompts user for signed decimal number and adds 1 to it.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz        "Enter a signed integer between -2147483648 and +2147483646: "

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        
        ldr     r0, promptAddr  @ prompt user
        bl      writeStr
        
        bl      getDecInt       @ convert it
        
        add     r0, r0, 1       @ increment user's number
        bl      putDecInt       @ print result
        bl      newLine
        
        mov     r0, 0           @ return 0;
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return

promptAddr:
        .word    prompt
@ getDecInt.s
@ Gets signed decimal integer from keyboard.
@ Calling sequence:
@       bl getDecInt
@ returns equivalent int
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    maxChars,12     @ max input chars
        .equ    inputString,-20 @ for input string
        .equ    locals,8        @ space for local vars

@ Useful source code constants
        .equ    POS,0
        .equ    NEG,1

@ The program
        .text
        .align  2
        .global getDecInt
        .type   getDecInt, %function
getDecInt:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        sub     sp, sp, locals  @ for the string
        
        add     r0, fp, inputString  @ place to store input
        mov     r1, maxChars    @ limit input length
        bl      readLn
        
        add     r0, fp, inputString  @ input string
        mov     r4, POS         @ assume postive int

        ldrb    r1, [r0]        @ get char
        cmp     r1, '-          @ minus sign?
        bne     checkPlus       @ no, check for plus sign
        mov     r4, NEG         @ yes, flag as neg
        add     r0, r0, 1       @ go to the number
        b       convert         @ and convert it
checkPlus:  
        cmp     r1, '+          @ plus sign?
        bne     convert         @ no, we're at the number
        add     r0, r0, 1       @ go to the number
convert:
        bl      uDecToInt
        
        cmp     r4, POS         @ positive int?
        beq     allDone         @ yes, we're done
        mvn     r0, r0          @ no, complement it
        add     r0, r0, 1       @ and finish negate       
allDone:        
        add     sp, sp, locals  @ deallocate local var
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return
@ putDecInt.s
@ Converts an int to the corresponding signed
@ decimal text string.
@ Calling sequence:
@       r0 <- int to print
@       bl putDecInt
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    decString,-20   @ for  string
        .equ    locals,8        @ space for local varsbr

@ Useful source code constants
        .equ    POS,0
        .equ    NEGBIT,0x80000000

@ The program
        .text
        .align  2
        .global putDecInt
        .type   putDecInt, %function
putDecInt:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        sub     sp, sp, locals  @ space for the string
        
        add     r4, fp, decString  @ place to store string
        mov     r1, '+          @ assume positive
        strb    r1, [r4]
        tst     r0, NEGBIT      @ negative int?
        beq     positive        @ no, go on
        mov     r1, '-          @ yes, need to negate
        strb    r1, [r4]
        mvn     r0, r0          @ complement
        add     r0, r0, 1       @ two's complement
positive:
        mov     r1, r0          @ int to convert
        add     r0, r4, 1       @ skip over sign char
        bl      uIntToDec

        add     r0, fp, decString  @ string to write
        bl      writeStr

        add     sp, sp, locals  @ deallocate local var
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

Exercises15.2Programming Exercise

Exercise1
Solution
@ reverseArray.s
@ Gets 10 integers from user then prints in reverse order.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    nElements,10    @ number of elements in array
        .equ    intArray,-52    @ array beginning
        .equ    locals,40       @ space for local vars

@ Constant program data
        .section .rodata
        .align  2
prompt:
        .asciz        "Enter an integer:\n"
display:
        .asciz        "In reverse order:\n"

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
        str     r4, [sp, 0]     @ save r4
        str     r5, [sp, 4]     @      r5
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        sub     sp, sp, locals  @ for the array
                
        add     r4, fp, intArray  @ address of array beginning
        mov     r5, 0           @ index = 0;
fillLoop:
        cmp     r5, nElements   @ all filled?
        bge     allFull         @ yes
        ldr     r0, promptAddr  @ no, prompt user
        bl      writeStr
        bl      getDecInt       @ get integer
        lsl     r1, r5, 2       @ offset is 4 * index
        str     r0, [r4, r1]    @ at index-th element
        add     r5, r5, 1       @ index++;
        b       fillLoop
allFull:
        ldr     r0, displayAddr @ nice message
        bl      writeStr
        
        add     r4, fp, intArray  @ address of array beginning
        mov     r5, 9           @ index = 9;
printLoop:
        lsl     r1, r5, 2       @ no, offset is 4 * index
        ldr     r0, [r4, r1]    @ at index-th element
        bl      putDecInt       @ print integer
        bl      newLine
        subs    r5, r5, 1       @ index--;
        bge     printLoop
allDone:
        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     r4, [sp, 0]     @ restore r4
        ldr     r5, [sp, 4]     @      r5
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @ restore sp
        bx      lr              @ return

promptAddr:
        .word    prompt
displayAddr:
        .word    display

Exercises15.5Programming Exercise

Exercise1
Solution
@ structPass3.s
@ Allocates two structs and gets values for user for
@ each struct, then displays the values.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "theTagStruct.s"  @ theTag struct defs.
        .equ    y,-36           @ y struct
        .equ    x,-24           @ x struct
        .equ    locals,24       @ space for the structs

@ Constant program data
        .section .rodata
        .align  2
displayX:
        .asciz        "x fields:\n"
displayY:
        .asciz        "y fields:\n"

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        sub     sp, sp, locals  @ for the structs
        
@ fill the x struct
        add     r0, fp, x       @ address of x struct
        bl      getStruct

@ fill the y struct
        add     r0, fp, y       @ address of y struct
        bl      getStruct

@ display x struct
        ldr     r0, displayXaddr
        bl      writeStr
        add     r0, fp, x         @ address of x struct
        bl      putStruct
        bl      newLine

@ display y struct
        ldr     r0, displayYaddr
        bl      writeStr
        add     r0, fp, y         @ address of y struct
        bl      putStruct
        bl      newLine

        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return
        
        .align  2
@ addresses of messages
displayXaddr:
        .word   displayX
displayYaddr:
        .word   displayY
@ getStruct.s
@ Gets values for a theTag struct from keyboard
@ Calling sequence:
@        r0 <- address of the struct
@        bl  getStruct
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "theTagStruct.s"  @ theTag struct defs.
        
@ Constant program data
        .section .rodata
        .align  2
charPrompt:
        .asciz        "Enter a character: "
intPrompt:
        .asciz        "Enter an integer: "

@ The program
        .text
        .align  2
        .global getStruct
        .type   getStruct, %function
getStruct:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r4, r0          @ pointer to the struct
        
        ldr     r0, charPromptAddr
        bl      writeStr        @ ask for a char
        bl      getChar         @ get it
        strb    r0, [r4, aChar] @ aStruct->aChar = firstChar;
        
        
        ldr     r0, intPromptAddr
        bl      writeStr        @ ask for a char
        bl      getDecInt       @ get it
        str     r0, [r4, anInt] @ aStruct->anInt = aNumber;

        ldr     r0, charPromptAddr
        bl      writeStr        @ ask for a char
        bl      getChar         @ get it
        strb    r0, [r4, anotherChar] @ aStruct->anotherChar = secondChar;

        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

        .align  2
@ addresses of messages
charPromptAddr:
        .word   charPrompt
intPromptAddr:
        .word   intPrompt
@ putStruct.s
@ Displays values for a theTag struct on screen
@ Calling sequence:
@        r0 <- address of the struct
@        bl  putStruct
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "theTagStruct.s"  @ theTag struct defs.
        
@ Constant program data
        .section .rodata
        .align  2
dispAChar:
        .asciz        "         aChar = "
dispAnInt:
        .asciz        "         anInt = "
dispOtherChar:
        .asciz        "   anotherChar = "

@ The program
        .text
        .align  2
        .global putStruct
        .type   putStruct, %function
putStruct:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r4, r0             @ pointer to the struct
        
        ldr     r0, dispACharAddr  @ display aChar
        bl      writeStr
        ldrb    r0, [r4, aChar]
        bl      putChar
        bl      newLine
        ldr     r0, dispAnIntAddr  @ display anInt
        bl      writeStr
        ldr     r0, [r4, anInt]
        bl      putDecInt
        bl      newLine
        ldr     r0, dispOtherCharAddr @ display anotherChar
        bl      writeStr
        ldrb    r0, [r4, anotherChar]
        bl      putChar
        bl      newLine

        mov     r0, 0              @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

        .align  2
@ addresses of messages
dispACharAddr:
        .word   dispAChar
dispAnIntAddr:
        .word   dispAnInt
dispOtherCharAddr:
        .word   dispOtherChar
@ getChar.s
@ Gets one char from keyboard.
@ Calling sequence:
@       bl getChar
@ returns char in low byte of r0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    maxChars,2      @ max input chars
        .equ    inputChar,-12   @ for input chars
        .equ    locals,8        @ space for local vars

@ The program
        .text
        .align  2
        .global getChar
        .type   getChar, %function
getChar:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        sub     sp, sp, locals  @ for the string
        
        add     r0, fp, inputChar  @ place to store input
        mov     r1, maxChars    @ limit input length
        bl      readLn

        ldrb    r0, [fp, inputChar] @ return inputChar
        
        add     sp, sp, locals  @ deallocate local var
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return

Exercises15.7Programming Exercise

Exercise1
Solution
@ incFraction.s
@ Gets values from user for a fraction, adds 1
@ to the fraction, and then displays the result.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    x,-12           @ x fraction object
        .equ    locals,8        @ space for fraction

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        sub     sp, sp, locals  @ for the structs
        
@ construct the fraction
        add     r0, fp, x       @ address of x struct
        bl      fractionConstr

@ get user input
        add     r0, fp, x       @ get user values
        bl      fractionGet

@ add 1
        add     r0, fp, x       @ add 1 to it
        mov     r1, 1 
        bl      fractionAddInt
        
@ display result
        add     r0, fp, x       @ get user values
        bl      fractionDisplay

        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return
@ fractionObject.s
@ field name definitions; requires 8 bytes
@ 2017-09-29: Bob Plantz

@ fraction object definition
        .equ    num,0    @ numerator
        .equ    den,4    @ denominator
@ fractionConstr.s
@ Construct a fraction object
@ Calling sequence:
@        r0 <- address of fraction variable
@        bl  fractionConstr
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "fractionObject.s"  @ fraction object defs.
        
@ The code
        .text
        .align  2
        .global fractionConstr
        .type   fractionConstr, %function
fractionConstr:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        
        mov     r1, 1           @ reasonable numerator
        str     r1, [r0, num]
        
        mov     r1, 2           @ reasonable denominator
        str     r1, [r0, den]

        mov     r0, 0           @ return 0;
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return
@ fractionGet.s
@ Gets values for a fraction from keyboard
@ Calling sequence:
@        r0 <- address of the struct
@        bl  getStruct
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "fractionObject.s"  @ fraction object defs.
        
@ Constant program data
        .section .rodata
        .align  2
numPrompt:
        .asciz        "  Enter numerator: "
denPrompt:
        .asciz        "Enter denominator: "

@ The code
        .text
        .align  2
        .global fractionGet
        .type   fractionGet, %function
fractionGet:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r4, r0          @ pointer to the object
        
        ldr     r0, numPromptAddr
        bl      writeStr        @ ask for numerator
        bl      getDecInt       @ get it
        str     r0, [r4, num]   @ store at this->num
                
        ldr     r0, denPromptAddr
        bl      writeStr        @ ask for denominator
        bl      getDecInt       @ get it
        str     r0, [r4, den]   @ store at this->den

        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

        .align  2
@ addresses of messages
numPromptAddr:
        .word   numPrompt
denPromptAddr:
        .word   denPrompt
@ fractionAddInt.s
@ Adds an integer to a fraction
@ Assumes (int X den) + num fits into 32 bits.
@ Calling sequence:
@        r0 <- address of the object
@        r1 <- integer to add
@        bl  fractionAddInt
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "fractionObject.s"  @ fraction object defs.
        
@ The code
        .text
        .align  2
        .global fractionAddInt
        .type   fractionAddInt, %function
fractionAddInt:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r4, r0          @ this pointer
        
        ldr     r0, [r4, den]   @ get denominator
        mul     r2, r1, r0      @ integer X denominator
        ldr     r0, [r4, num]   @ get numerator
        add     r2, r2, r0      @ numerator + (int X den)
        str     r2, [r4, num]   @ save new numerator
        
        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return
@ fractionDisplay.s
@ Displays a fraction struct on screen
@ Calling sequence:
@        r0 <- address of the struct
@        bl  fractionDisplay
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "fractionObject.s"  @ fraction object defs.
        
@ The code
        .text
        .align  2
        .global fractionDisplay
        .type   fractionDisplay, %function
fractionDisplay:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r4, r0          @ this pointer
        
        ldr     r0, [r4, num]   @ display numerator
        bl      putDecInt
        mov     r0, '/          @ slash for fraction
        bl      putChar
        ldr     r0, [r4, den]   @ display denominator
        bl      putDecInt
        bl      newLine

        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return
@ putChar.s
@ Writes a character to the standard output (screen).
@ Calling sequence:
@       r0 <- the character
@       bl    putChar
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    STDOUT,1
        .equ    theChar,-5     @ for  string
        .equ    locals,8       @ space for local var

@ The code
        .text
        .align  2
        .global putChar
        .type   putChar, %function
putChar:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        sub     sp, sp, locals

        strb    r0, [fp, theChar]  @ write needs address
        mov     r0, STDOUT      @ write to screen
        add     r1, fp, theChar    @ address of theChar
        mov     r2, 1           @ write 1 byte
        bl      write

        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return

Exercises16.2Programming Exercise

Exercise1
Solution

Refer to Equation (16.1.1).

  • \(i = -1\)
  • While (\(F \ne 0\)) AND (want-more-bits)

    • \(F = 2 \times F\)

    • \(d_{i} = int(F)\)

    • \(F = F - d_{i}\)

    • \(i = i - 1\)

Exercises16.6Exercises

Exercise1
Solution

  1. Compute \(s\text{,}\) \(e+127\text{,}\) and \(f\text{.}\)

    \begin{align*} s &= \binary{0}\\ e + 127 &= \binary{00000000}_{2}\\ e &= -127_{10}\\ f &= \binary{00000000000000000000000} \end{align*}
  2. Finally, plug these values into Equation (16.5.1). (Remember to add the hidden bit.)

    \begin{align*} (-1)^0 \times 1.00\dots 00 \times 2^{-127} &= \mbox{a very small number}\\ &\ne 0.0 \end{align*}

    so we do need the special case.

Exercise2
Answer

  1. \(\hex{3f80 0000}\)

  2. \(\hex{bdcc cccd}\)

  3. \(\hex{44fc 0000}\)

  4. \(\hex{3b80 0000}\)

  5. \(\hex{c543 5500}\)

  6. \(\hex{3ea8 f5c3}\)

  7. \(\hex{3f2b 851f}\)

  8. \(\hex{4048 f5c3}\)

Exercise3
Answer

  1. \(+2.0\)

  2. \(-1.0\)

  3. \(+0.0625\)

  4. \(-16.03125\)

  5. \(100.03125\)

  6. \(1.2\)

  7. \(123.449997\)

  8. \(-54.320999\)

Exercises18.6Programming Exercise

Exercise1
Solution
@ locatePeripherals.s
@ Determines the beginning address of peripherals.
@ Link with /opt/vc/lib/libbcm_host.so
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constant program data
        .section  .rodata
        .align  2
formatMsg:
        .asciz	 "Peripheral addresses begin at %p\n"

@ Program code
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        
        bl      bcm_host_get_peripheral_address @ get the address
        mov     r1, r0          @ argument for printf
        ldr     r0, formatMsgAddr  @ printf("%i + %i = %i\n",
        bl      printf

        mov     r0, 0           @ return 0;
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return
        bx      lr              @ return

        .align  2
formatMsgAddr:
        .word   formatMsg

Exercises19.3Programming Exercise

Exercise1
Solution

See Listing 19.2.6 for gpioPinFSelect and Listing 19.2.8 for gpioPinSet.

@ blinkLED.s
@ Blinks LED connected between pins 1 and 11 on Raspberry Pi
@ GPIO connector once a second for five seconds.
@ 2017-09-30: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    PERIPH,0x3f000000   @ RPi 2 & 3 peripherals
@        .equ    PERIPH,0x20000000   @ RPi zero & 1 peripherals
        .equ    GPIO_OFFSET,0x200000  @ start of GPIO device
@ The following are defined in /usr/include/asm-generic/fcntl.h:
@ Note that the values are specified in octal.
        .equ    O_RDWR,00000002   @ open for read/write
        .equ    O_DSYNC,00010000
        .equ    __O_SYNC,04000000
        .equ    O_SYNC,__O_SYNC|O_DSYNC
@ The following are defined in /usr/include/asm-generic/mman-common.h:
        .equ    PROT_READ,0x1   @ page can be read
        .equ    PROT_WRITE,0x2  @ page can be written
        .equ    MAP_SHARED,0x01 @ share changes
@ The following are defined by me:
        .equ    O_FLAGS,O_RDWR|O_SYNC @ open file flags
        .equ    PROT_RDWR,PROT_READ|PROT_WRITE
        .equ    NO_PREF,0
        .equ    PAGE_SIZE,4096  @ Raspbian memory page
        .equ    INPUT,0         @ use pin for input
        .equ    OUTPUT,1        @ use pin for ouput
        .equ    ONE_SEC,1       @ sleep one second
        .equ    PIN17,17        @ pin set bit
        .equ    FILE_DESCRP_ARG,0   @ file descriptor
        .equ    DEVICE_ARG,4        @ device address
        .equ    STACK_ARGS,8    @ includes sp 8-byte align

@ Constant program data
        .section .rodata
        .align  2
device:
        .asciz  "/dev/gpiomem"
devErr:
        .asciz  "Cannot open /dev/gpiomem\n"
memErr:
        .asciz  "Cannot map /dev/gpiomem\n"

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 24      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     r5, [sp, 8]     @      r5
        str     r6, [sp,12]     @      r6
        str     fp, [sp, 16]    @      fp
        str     lr, [sp, 20]    @      lr
        add     fp, sp, 20      @ set our frame pointer
        sub     sp, sp, STACK_ARGS

@ Open /dev/gpiomem for read/write and syncing        
        ldr     r0, deviceAddr  @ address of /dev/gpiomem
        ldr     r1, openMode    @ flags for accessing device
        bl      open
        cmp     r0, -1          @ check for error
        bne     gpiomemOK       @ no error, continue
        ldr     r0, devErrAddr  @ error, tell user
        bl      printf
        b       allDone         @ and end program
        
gpiomemOK:      
        mov     r4, r0          @ use r4 for file descriptor

@ Map the GPIO registers to a main memory location so we can access them
        str     r4, [sp, FILE_DESCRP_ARG] @ /dev/gpiomem file descriptor
        ldr     r0, gpio        @ address of GPIO
        str     r0, [sp, DEVICE_ARG]      @ location of GPIO
        mov     r0, NO_PREF     @ let kernel pick memory
        mov     r1, PAGE_SIZE   @ get 1 page of memory
        mov     r2, PROT_RDWR   @ read/write this memory
        mov     r3, MAP_SHARED  @ share with other processes
        bl      mmap
        cmp     r0, -1          @ check for error
        bne     mmapOK          @ no error, continue
        ldr     r0, memErrAddr @ error, tell user
        bl      printf
        b       closeDev        @ and close /dev/gpiomem
        
@ All OK, blink the LED
mmapOK:                
        mov     r5, r0          @ use r5 for programming memory address
        mov     r0, r5          @ programming memory
        mov     r1, PIN17       @ pin to blink
        mov     r2, OUTPUT      @ it's an output
        bl      gpioPinFSelect  @ select function

        mov     r6, 5           @ blink five times
loop:
        mov     r0, r5          @ GPIO programming memory
        mov     r1, PIN17
        bl      gpioPinClr
        mov     r0, ONE_SEC     @ wait a second
        bl      sleep
        mov     r0, r5
        mov     r1, PIN17
        bl      gpioPinSet
        mov     r0, ONE_SEC     @ wait a second
        bl      sleep
        subs    r6, r6, 1       @ decrement counter
        bgt     loop            @ loop until 0
        
        mov     r0, r5          @ memory to unmap
        mov     r1, PAGE_SIZE   @ amount we mapped
        bl      munmap          @ unmap it

closeDev:
        mov     r0, r4          @ /dev/gpiomem file descriptor
        bl      close           @ close the file

allDone:        
        mov     r0, 0           @ return 0;
        add     sp, sp, STACK_ARGS  @ fix sp
        ldr     r4, [sp, 4]     @ restore r4
        ldr     r5, [sp, 8]     @      r5
        ldr     r6, [sp,12]     @      r6
        ldr     fp, [sp, 16]    @      fp
        ldr     lr, [sp, 20]    @      lr
        add     sp, sp, 24      @      sp
        bx      lr              @ return
        
        .align  2
@ addresses of messages
deviceAddr:
        .word   device
openMode:
        .word   O_FLAGS
gpio:
        .word   PERIPH+GPIO_OFFSET
devErrAddr:
        .word   devErr
memErrAddr:
        .word   memErr
@ gpioPinClr.s
@ Clears a GPIO pin. Assumes that GPIO registers
@ have been mapped to programming memory.
@ Calling sequence:
@       r0 <- address of GPIO in mapped memory
@       r1 <- pin number
@       bl gpioPinClr
@ 2017-09-30: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    PIN,1           @ 1 bit for pin
        .equ    PINS_IN_REG,32
        .equ    GPCLR0,0x28     @ clear register offset

@ The program
        .text
        .align  2
        .global gpioPinClr
        .type   gpioPinClr, %function
gpioPinClr:
        sub     sp, sp, 16      @ space for saving regs
        str     r4, [sp, 0]     @ save r4
        str     r5, [sp, 4]     @      r5
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        add     r4, r0, GPCLR0  @ pointer to GPSET regs.
        mov     r5, r1          @ save pin number
        
@ Compute address of GPSET register and pin field        
        mov     r3, PINS_IN_REG @ divisor
        udiv    r0, r5, r3      @ GPSET number
        mul     r1, r0, r3      @ compute remainder
        sub     r1, r5, r1      @     for relative pin position
        lsl     r0, r0, 2       @ 4 bytes in a register
        add     r0, r0, r4      @ address of GPSETn
        
@ Set up the GPIO pin funtion register in programming memory
        ldr     r2, [r0]        @ get entire register
        mov     r3, PIN         @ one pin
        lsl     r3, r3, r1      @ shift to pin position
        orr     r2, r2, r3      @ clear bit
        str     r2, [r0]        @ update register
        
        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 0]     @ restore r4
        ldr     r5, [sp, 4]     @      r5
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @ restore sp
        bx      lr              @ return