Appendix E
Exercise Solutions

The solutions to most of the exercises in the book are in this Appendix. You should attempt to work the exercise before looking at the solution. But don’t allow yourself to get bogged down. If the solution does not come to you within a reasonable amount of time, peek at the solution for a hint.

A word of warning: I have proofread these solutions many times. Each time has turned up several errors. I am amazed at how difficult it is to make everything perfect. If you find an error, please email me and I will try to correct the next printing.

When reading my programming solutions, be aware that my goal is to present simple, easy-to-read code that illustrates the point. I have not tried to optimize, neither for size nor performance.

I am also aware that each of us has our own programming style. Yours probably differs from mine. If you are working with an instructor, I encourage you to discuss programming style with him or her. I probably will not change my style, but I support other people’s desire to use their own style.

E.2 Data Storage Formats

2 -1

a)

4567

b)

89ab

c)

fedc

d)

0250

2 -2

a)

1000 0011 1010 1111

b)

1001 0000 0000 0001

c)

1010 1010 1010 1010

d)

0101 0101 0101 0101

2 -3

a)

32

b)

48

c)

4

d)

16

e)

8

f)

32

2 -4

a)

2

b)

8

c)

16

d)

3

e)

5

f)

2

2 -5

r = 10, n = 8, d7 = 2, d6 = 9, d5 = 4, d4 = 5, d3 = 8, d2 = 2, d1 = 5, d0 = 4.

r = 16, n = 8, d7 = 2, d6 = 9, d5 = 4, d4 = 5, d3 = 8, d2 = 2, d1 = 5, d0 = 4.

2 -6

a)

170

b)

85

c)

240

d)

15

e)

128

f)

99

g)

123

h)

255

2 -7

a)

43981

b)

4660

c)

65244

d)

2000

e)

32768

f)

1024

g)

65535

h)

12345

2 -8

  1. compute the value of each power of 16 in decimal.
  2. multiply each power of 16 by its corresponding di.
  3. sum the terms.
a)

160

b)

80

c)

255

d)

137

e)

100

f)

12

g)

17

h)

200

2 -9

  1. compute the value of each power of 16 in decimal.
  2. multiply each power of 16 by its corresponding di.
  3. sum the terms.
a)

40960

b)

65535

c)

1024

d)

4369

e)

34952

f)

400

g)

43981

h)

21845

2 -10

a)

64

b)

7b

c)

0a

d)

58

e)

ff

f)

10

g)

20

h)

80

2 -11

a)

0400

b)

03e8

c)

8000

d)

7fff

e)

0100

f)

ffff

g)

07d5

h)

abcd

2 -12

Since there are 12 values, we need 4 bits. Any 4-bit code would work. For example,

code grade
0000 A
0001 A-
0010 B+
0011 B
0100 B-
0101 C+
0110 C
0111 C-
1000 D+
1001 D
1010 D-
1011 F
2 -13

The addressing in Figure 2.1 uses only four bits. This limits us to a 16-byte addressing space. In order to increase our space to 17 bytes, we need another bit for the address. The 17th byte would be number 10000.

2 -14

      address  contents        address  contents  
       00000000: 106            00000008: 240  
       00000001: 240            00000009: 2  
       00000002: 94             0000000a: 51  
       00000003: 0              0000000b: 60  
       00000004: 255            0000000c: 195  
       00000005: 81             0000000d: 60  
       00000006: 207            0000000e: 85  
       00000007: 24             0000000f: 170

2 -15

      address   contents       address   contents  
       00000000: 0000 0000      00000008: 0000 1000  
       00000001: 0000 0001      00000009: 0000 1001  
       00000002: 0000 0010      0000000a: 0000 1010  
       00000003: 0000 0011      0000000b: 0000 1011  
       00000004: 0000 0100      0000000c: 0000 1100  
       00000005: 0000 0101      0000000d: 0000 1101  
       00000006: 0000 0110      0000000e: 0000 1110  
       00000007: 0000 0111      0000000f: 0000 1111

2 -16

      address  contents        address  contents  
       00000000: 00             00000008: 08  
       00000001: 01             00000009: 09  
       00000002: 02             0000000a: 0a  
       00000003: 03             0000000b: 0b  
       00000004: 04             0000000c: 0c  
       00000005: 05             0000000d: 0d  
       00000006: 06             0000000e: 0e  
       00000007: 08             0000000f: 0f

2 -17

The range of 32-bit unsigned ints is 0 – 4,294,967,295, so four bytes will be required. If the storage area begins at byte number 0x2fffeb96, the number will also occupy bytes number 0x2fffeb97, 0x2fffeb98, 0x2fffeb99.

2 -18

      address  contents        address  contents  
       00001000: 00             0000100f: 0f  
       00001001: 01             00001010: 10  
       00001002: 02             00001011: 11  
       00001003: 03             00001012: 12  
       00001004: 04             00001013: 13  
       00001005: 05             00001014: 14  
       00001006: 06             00001015: 15  
       00001007: 07             00001016: 16  
       00001008: 08             00001017: 17  
       00001009: 09             00001018: 18  
       0000100a: 0a             00001019: 19  
       0000100b: 0b             0000101a: 1a  
       0000100c: 0c             0000101b: 1b  
       0000100d: 0d             0000101c: 1c  
       0000100e: 0e             0000101d: 1d

2 -19

     number  letter grade  
         0          A  
         1          B  
         2          C  
         3          D  
         4          F

2 -26

 
1/* 
2 * echoDecHexAddr.c 
3 * Asks user to enter a number in decimal or hexadecimal 
4 * then echoes it in both bases, also showing where values 
5 * are stored. 
6 * 
7 * Bob Plantz - 19 June 2009 
8 */ 
9 
10#include <stdio.h> 
11 
12int main(void) 
13{ 
14    int x; 
15    unsigned int y; 
16 
17    while(1) 
18    { 
19        printf("Enter a decimal integer: "); 
20        scanf("%i", &x); 
21        if (x == 0) break; 
22 
23        printf("Enter a bit pattern in hexadecimal: "); 
24        scanf("%x", &y); 
25        if (y == 0) break; 
26 
27        printf("%i is stored as %#010x at %p, and\n", x, x, &x); 
28        printf("%#010x represents the decimal integer %d stored at %p\n\n", 
29             y, y, &y); 
30    } 
31    printf("End of program.\n"); 
32 
33    return 0; 
34}
2 -28

 
1/* 
2 * stringInHex.c 
3 * displays "Hello world" in hex. 
4 * 
5 * Bob Plantz - 19 June 2009 
6 */ 
7 
8#include <stdio.h> 
9 
10int main(void) 
11{ 
12    char *stringPtr = "Hello world.\n"; 
13 
14    while (*stringPtr != \0) 
15    { 
16        printf("%p:  ", stringPtr); 
17        printf("0x%02x\n", *stringPtr); 
18        stringPtr++; 
19    } 
20    printf("%p:  ", stringPtr); 
21    printf("0x%02x\n", *stringPtr); 
22 
23    return 0; 
24}
2 -29

Keyboard input is line buffered by the operating system and is not available to the application program until the user presses the enter key. This action places two characters in the keyboard buffer – the character key pressed and the end of line character. (The “end of line” character differs in different operating systems.)

The call to the read function gets one character from the keyboard buffer – the one corresponding to the key the user pressed. Since there is a breakpoint at the instruction following the call to read, control returns to the debugger, gdb. But the end of line character is still in the keyboard buffer, and the operating system dutifully provides it to gdb.

The net result is the same as if you had pushed the enter key immediately in response to gdb’s prompt. This causes gdb to execute the previous command, which was the continue command. So the program immediately loops back to its prompt.

Experiment with this. Try to enter more than one character before pressing the enter key. It is all very consistent. You just have to think through exactly which keys you are pressing when using the debugger to determine what your call to read are doing.

2 -30

 
1/* 
2 * echoString1.c 
3 * Echoes a string entered by user. 
4 * 
5 * Bob Plantz - 19 June 2009 
6 */ 
7 
8#include <unistd.h> 
9#include <string.h> 
10 
11int main(void) 
12{ 
13    char aString[200]; 
14    char *stringPtr = aString; 
15 
16    write(STDOUT_FILENO, "Enter a text string: ", 
17         strlen("Enter a text string: "));  // prompt user 
18 
19    read(STDIN_FILENO, stringPtr, 1);       // get first character 
20    while (*stringPtr != \n)              // look for end of line 
21    { 
22        stringPtr++;                        // move to next location 
23        read(STDIN_FILENO, stringPtr, 1);   // get next characte 
24    } 
25 
26    // now echo for user 
27    write(STDOUT_FILENO, "You entered:\n", 
28         strlen("You entered:\n")); 
29    stringPtr = aString; 
30    do 
31    { 
32        write(STDOUT_FILENO, stringPtr, 1); 
33        stringPtr++; 
34    } while (*stringPtr != \n); 
35    write(STDOUT_FILENO, stringPtr, 1); 
36 
37    return 0; 
38}
2 -31

 
1/* 
2 * echoString2.c 
3 * Echoes a string entered by user. Converts input 
4 * to C-style string. 
5 * Bob Plantz - 19 June 2009 
6 */ 
7 
8#include <stdio.h> 
9#include <unistd.h> 
10#include <string.h> 
11 
12int main(void) 
13{ 
14    char aString[200]; 
15    char *stringPtr = aString; 
16 
17    write(STDOUT_FILENO, "Enter a text string: ", 
18         strlen("Enter a text string: ")); // prompt user 
19 
20    read(STDIN_FILENO, stringPtr, 1);      // get first character 
21    while (*stringPtr != \n)             // look for end of line 
22    { 
23        stringPtr++;                       // move to next location 
24        read(STDIN_FILENO, stringPtr, 1);  // get next character 
25    } 
26    *stringPtr = \0;                     // make into C string 
27 
28    // now echo for user 
29    printf("You entered:\n%s\n", aString); 
30 
31    return 0; 
32}
2 -32

 
1/* 
2 * echoString3.c 
3 * Echoes a string entered by user. 
4 * 
5 * Bob Plantz - 19 June 2009 
6 */ 
7 
8#include "readLn.h" 
9#include "writeStr.h" 
10 
11int main(void) 
12{ 
13    char aString[STRLEN];  // limited to 5 for testing readStr 
14                      // change to 200 for use 
15    writeStr("Enter a text string: "); 
16    readLn(aString, STRLEN); 
17    writeStr("You entered:\n"); 
18    writeStr(aString); 
19    writeStr("\n"); 
20 
21    return 0; 
22}
 
1/* 
2 * writeStr.h 
3 * Writes a line to standard out. 
4 * 
5 * input: 
6 *    pointer to C-style text string 
7 * output: 
8 *    to screen 
9 *    returns number of chars written 
10 * 
11 * Bob Plantz - 19 June 2009 
12 */ 
13 
14#ifndef WRITESTR_H 
15#define WRITESTR_H 
16int writeStr(char *); 
17#endif
 
1/* 
2 * writeStr.c 
3 * Writes a line to standard out. 
4 * 
5 * input: 
6 *    pointer to C-style text string 
7 * output: 
8 *    to screen 
9 *    returns number of chars written 
10 * 
11 * Bob Plantz - 19 June 2009 
12 */ 
13 
14#include <unistd.h> 
15#include "writeStr.h" 
16 
17int writeStr(char *stringAddr) 
18{ 
19    int count = 0; 
20 
21    while (*stringAddr != \0) 
22    { 
23        write(STDOUT_FILENO, stringAddr, 1); 
24        count++; 
25        stringAddr++; 
26    } 
27 
28    return count; 
29}
 
1/* 
2 * readLn.h 
3 * Reads a line from standard in. 
4 * Drops newline character. Eliminates 
5 * excess characters from input buffer. 
6 * 
7 * input: 
8 *    from keyboard 
9 * output: 
10 *    null-terminated text string 
11 *    returns number of chars in text string 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#ifndef READLN_H 
17#define READLN_H 
18int readLn(char *, int); 
19#endif
 
1/* 
2 * readLn.c 
3 * Reads a line from standard in. 
4 * Drops newline character. Eliminates 
5 * excess characters from input buffer. 
6 * 
7 * input: 
8 *    from keyboard 
9 * output: 
10 *    null-terminated text string 
11 *    returns number of chars in text string 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#include <unistd.h> 
17#include "readLn.h" 
18 
19int readLn(char *stringAddr, int maxLength) 
20{ 
21    int count = 0; 
22    maxLength--;          // allow space for NUL 
23    read(STDIN_FILENO, stringAddr, 1); 
24    while (*stringAddr != \n) 
25    { 
26        if (count < maxLength) 
27        { 
28            count++; 
29            stringAddr++; 
30        } 
31        read(STDIN_FILENO, stringAddr, 1); 
32    } 
33    *stringAddr = \0;   // terminate C string 
34 
35   return count; 
36}

E.3 Computer Arithmetic

3 -1

four

3 -2

Store a digit in every four bits. Thus, the lowest-order digit would be stored in bits 7 – 0, the next lowest-order in 15 – 8, etc., with the highest-order digit in bits 31 – 24.

No, binary addition does not work. For example, let’s consider 48 + 27:

 number       32bits(hex)
      48  −→   00000048
----+27--−→  -00000027---
      75       0000007f

3 -3

See next answer.

3 -4

No, it doesn’t work. The problem is that the range of 4-bit signed numbers in two’s complement format is 8 x +7, and (+4) + (+5) exceeds this range.

 number       4bits
   (+4)  −→   0100
-+-(+5)--−→  -0101-
   (− 7) ← −  1001

3 -5

No, it doesn’t work. The problem is that the range of 4-bit signed numbers in two’s complement format is 8 x +7, and (4) + (5) exceeds this range.

 number       4bits
   (− 4) −→   1100
 + (− 5) −→   1011
---(+7)--← − -0111-

3 -6

Adding any number to its negative will set the CF to one and the OF to zero. The sum is 2n, where n is the number of bits used for representing the signed integer. That is, the sum is one followed by n zeroes. The one gets recorded in the CF. Since the CF is irrelevant in two’s complement arithmetic, the result — n zeroes — is correct.

In two’s complement, zero does not have a representation of opposite sign. (-0.0 does exist in IEEE 754 floating point.) Also, 2n1 does not have a representation of opposite sign.

3 -7

a)

+85

b)

-86

c)

-16

d)

+15

e)

-128

f)

+99

g)

+123

3 -8

a)

+4660

b)

-4660

c)

-292

d)

+2000

e)

-32768

f)

+1024

g)

-1

h)

+30767

3 -9

a)

64

b)

ff

c)

f6

d)

58

e)

7f

f)

f0

g)

e0

h)

80

3 -10

a)

0400

b)

fc00

c)

ffff

d)

7fff

e)

ff00

f)

8000

g)

8001

h)

ff80

3 -11

a)

ff
CF = 0 unsigned right
OF = 0 signed right

b)

45
CF = 1 unsigned wrong
OF = 0 signed right

c)

fb
CF = 0 unsigned right
OF = 0 signed right

d)

de
CF = 0 unsigned right
OF = 1 signed wrong

e)

0e
CF = 1 unsigned wrong
OF = 0 signed right

f)

00
CF = 1 unsigned wrong
OF = 1 signed wrong

3 -12

a)

0000
CF = 1 unsigned wrong
OF = 0 signed right

b)

1110
CF = 1 unsigned wrong
OF = 0 signed right

c)

0000
CF = 1 unsigned wrong
OF = 1 signed wrong

d)

03ff
CF = 1 unsigned wrong
OF = 0 signed right

e)

7fff
CF = 0 unsigned right
OF = 0 signed right

f)

7fff
CF = 1 unsigned wrong
OF = 1 signed wrong

3 -14

 
1/* 
2 * hexTimesTen.c 
3 * Multiplies a hex number by 10. 
4 * Bob Plantz - 19 June 2009 
5 */ 
6 
7#include "readLn.h" 
8#include "writeStr.h" 
9#include "hex2int.h" 
10#include "int2hex.h" 
11 
12int main(void) 
13{ 
14    char aString[9]; 
15    unsigned int x; 
16 
17    writeStr("Enter a hex number: "); 
18    readLn(aString, 9); 
19    x = hex2int(aString); 
20    x *= 10; 
21    int2hex(aString, x); 
22    writeStr("Multiplying by ten gives: "); 
23    writeStr(aString); 
24    writeStr("\n"); 
25 
26    return 0; 
27}
 
1/* 
2 * hex2int.h 
3 * 
4 * Converts a hexadecimal text string to corresponding 
5 * unsigned int format. 
6 * Assumes text string is valid hex chars. 
7 * 
8 * input: 
9 *    pointer to null-terminated text string 
10 * output: 
11 *    returns the unsigned int. 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#ifndef HEX2INT_H 
17#define HEX2INT_H 
18 
19unsigned int hex2int(char *hexString); 
20 
21#endif
 
1/* 
2 * hex2int.c 
3 * 
4 * Converts a hexadecimal text string to corresponding 
5 * unsigned int format. 
6 * Assumes text string is valid hex chars. 
7 * 
8 * input: 
9 *    pointer to null-terminated text string 
10 * output: 
11 *    returns the unsigned int. 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#include "hex2int.h" 
17 
18unsigned int hex2int(char *hexString) 
19{ 
20    unsigned int x; 
21    unsigned char aChar; 
22 
23    x = 0;                      // initialize result 
24    while (*hexString != \0)  // end of string? 
25    { 
26        x = x << 4;             // make room for next four bits 
27        aChar = *hexString; 
28        if (aChar <= 9) 
29            x = x + (aChar & 0x0f); 
30        else 
31        { 
32            aChar = aChar & 0x0f; 
33            aChar = aChar + 9; 
34            x = x + aChar; 
35        } 
36        hexString++; 
37    } 
38 
39    return x; 
40}
 
1/* 
2 * int2hex.h 
3 * 
4 * Converts an unsigned int to corresponding 
5 * hex text string format. 
6 * Assumes char array is big enough. 
7 * 
8 * input: 
9 *    unsigned int 
10 * output: 
11 *    null-terminated text string 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#ifndef INT2HEX_H 
17#define INT2HEX_H 
18 
19void int2hex(char *hexString, unsigned int number); 
20 
21#endif
 
1/* 
2 * int2hex.c 
3 * 
4 * Converts an unsigned int to corresponding 
5 * hex text string format. 
6 * Assumes char array is big enough. 
7 * 
8 * input: 
9 *    unsigned int 
10 * output: 
11 *    null-terminated text string 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#include "int2hex.h" 
17 
18void int2hex(char *hexString, unsigned int number) 
19{ 
20    unsigned char aChar; 
21    int i; 
22 
23    hexString[8] = \0;        // install string terminator 
24    for (i = 7; i >= 0; i--) 
25    { 
26        aChar = number & 0x0f;  // get four bits 
27        if (aChar <= 9) 
28            aChar += 0; 
29        else 
30            aChar = aChar - 10 + a; 
31        hexString[i] = aChar; 
32        number = number >> 4; 
33    } 
34}

See Section E.2 for writeStr and readLn.

3 -15

 
1/* 
2 * binTimesTen.c 
3 * Multiplies a hex number by 10. 
4 * 
5 * Bob Plantz - 19 June 2009 
6 */ 
7 
8#include "readLn.h" 
9#include "writeStr.h" 
10#include "bin2int.h" 
11#include "int2bin.h" 
12 
13int main(void) 
14{ 
15    char aString[33]; 
16    unsigned int x; 
17 
18    writeStr("Enter a binary number: "); 
19    readLn(aString, 33); 
20    x = bin2int(aString); 
21    x *= 10; 
22    int2bin(aString, x); 
23    writeStr("Multiplying by ten gives: "); 
24    writeStr(aString); 
25    writeStr("\n"); 
26 
27    return 0; 
28}
 
1/* 
2 * bin2int.h 
3 * 
4 * bin2int.c 
5 * Converts a binary text string to corresponding 
6 * unsigned int format. 
7 * Assumes text string contains valid binary chars. 
8 * 
9 * input: 
10 *    pointer to null-terminated text string 
11 * output: 
12 *    returns the unsigned int. 
13 * 
14 * Bob Plantz - 19 June 2009 
15 */ 
16 
17#ifndef BIN2INT_H 
18#define BIN2INT_H 
19 
20unsigned int bin2int(char *binString); 
21 
22#endif
 
1/* 
2 * bin2int.c 
3 * Converts a binary text string to corresponding 
4 * unsigned int format. 
5 * Assumes text string contains valid binary chars. 
6 * 
7 * input: 
8 *    pointer to null-terminated text string 
9 * output: 
10 *    returns the unsigned int. 
11 * 
12 * Bob Plantz - 19 June 2009 
13 */ 
14 
15#include "bin2int.h" 
16 
17unsigned int bin2int(char *binString) 
18{ 
19    unsigned int x; 
20    unsigned char aChar; 
21 
22    x = 0;                      // initialize result 
23    while (*binString != \0)  // end of string? 
24    { 
25        x = x << 1;             // make room for next bit 
26        aChar = *binString; 
27        x |= (0x1 & aChar);     // sift out the bit 
28        binString++; 
29    } 
30 
31    return x; 
32}
 
1/* 
2 * int2bin.h 
3 * 
4 * Converts an unsigned int to corresponding 
5 * binary text string format. 
6 * Assumes char array is big enough. 
7 * 
8 * input: 
9 *    unsigned int 
10 * output: 
11 *    null-terminated text string 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#ifndef INT2BIN_H 
17#define INT2BIN_H 
18 
19void int2bin(char *binString, unsigned int number); 
20 
21#endif
 
1/* 
2 * int2bin.c 
3 * 
4 * Converts an unsigned int to corresponding 
5 * binary text string format. 
6 * Assumes char array is big enough. 
7 * 
8 * input: 
9 *    unsigned int 
10 * output: 
11 *    null-terminated text string 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#include "int2bin.h" 
17 
18void int2bin(char *binString, unsigned int number) 
19{ 
20    int i; 
21 
22    binString[32] = \0;      // install string terminator 
23    for (i = 31; i >= 0; i--) 
24    { 
25        if (number & 0x01) 
26            binString[i] = 1; 
27        else 
28            binString[i] = 0; 
29        number = number >> 1; 
30    } 
31}

See Section E.2 for writeStr and readLn.

3 -16

 
1/* 
2 * uDecTimesTen.c 
3 * Multiplies a decimal number by 10. 
4 * Bob Plantz - 20 June 1009 
5 */ 
6 
7#include "readLn.h" 
8#include "writeStr.h" 
9#include "udec2int.h" 
10#include "int2bin.h" 
11 
12int main(void) 
13{ 
14    char aString[33]; 
15    unsigned int x; 
16 
17    writeStr("Enter a decimal number: "); 
18    readLn(aString, 33); 
19    x = udec2int(aString); 
20    x *= 10; 
21    int2bin(aString, x); 
22    writeStr("Multiplying by ten gives (in binary): "); 
23    writeStr(aString); 
24    writeStr("\n"); 
25 
26    return 0; 
27}
 
1/* 
2 * uDec2int.h 
3 * 
4 * Converts a decimal text string to corresponding 
5 * unsigned int format. 
6 * Assumes text string is valid decimal chars. 
7 * 
8 * input: 
9 *    pointer to null-terminated text string 
10 * output: 
11 *    returns the unsigned int. 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#ifndef UDEC2INT_H 
17#define UDEC2INT_H 
18 
19unsigned int uDec2int(char *decString); 
20 
21#endif
 
1/* 
2 * uDec2int.c 
3 * 
4 * Converts a decimal text string to corresponding 
5 * unsigned int format. 
6 * Assumes text string is valid decimal chars. 
7 * 
8 * input: 
9 *    pointer to null-terminated text string 
10 * output: 
11 *    returns the unsigned int. 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#include "uDec2int.h" 
17 
18unsigned int uDec2int(char *decString) 
19{ 
20    unsigned int x; 
21    unsigned char aChar; 
22 
23    x = 0;                       // initialize result 
24    while (*decString != \0)   // end of string? 
25    { 
26        x *= 10; 
27        aChar = *decString; 
28        x += (0xf & aChar); 
29        decString++; 
30    } 
31 
32    return x; 
33}

See above for int2bin. See Section E.2 for writeStr and readLn.

3 -17

 
1/* 
2 * sDecTimesTen.c 
3 * Multiplies a signed decimal number by 10 
4 * and shows result in binary. 
5 * Bob Plantz - 21 June 2009 
6 */ 
7 
8#include "readLn.h" 
9#include "writeStr.h" 
10#include "sDec2int.h" 
11#include "int2bin.h" 
12 
13int main(void) 
14{ 
15    char aString[33]; 
16    int x; 
17 
18    writeStr("Enter a signed decimal number: "); 
19    readLn(aString, 33); 
20    x = sDec2int(aString); 
21    x *= 10; 
22    int2bin(aString, x); 
23    writeStr("Multiplying by ten gives (in binary): "); 
24    writeStr(aString); 
25    writeStr("\n"); 
26 
27    return 0; 
28}
 
1/* 
2 * sDec2int.h 
3 * 
4 * Converts a decimal text string to corresponding 
5 * signed int format. 
6 * Assumes text string is valid decimal chars. 
7 * 
8 * input: 
9 *    pointer to null-terminated text string 
10 * output: 
11 *    returns the signed int. 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#ifndef SDEC2INT_H 
17#define SDEC2INT_H 
18 
19int sDec2int(char *decString); 
20 
21#endif
 
1/* 
2 * sDec2int.c 
3 * 
4 * Converts a decimal text string to corresponding 
5 * signed int format. 
6 * Assumes text string is valid decimal chars. 
7 * 
8 * input: 
9 *    pointer to null-terminated text string 
10 * output: 
11 *    returns the signed int. 
12 * 
13 * Bob Plantz - 19 June 2009 
14 */ 
15 
16#include "uDec2int.h" 
17#include "sDec2int.h" 
18 
19int sDec2int(char *decString) 
20{ 
21    int x; 
22    int negative = 0; 
23 
24    if (*decString == -) 
25    { 
26       negative = 1; 
27       decString++; 
28    } 
29    else 
30    { 
31        if (*decString == +) 
32            decString++; 
33    } 
34 
35    x = uDec2int(decString); 
36 
37    if (negative) 
38       x *= -1; 
39 
40    return x; 
41}

See above for int2bin and uDec2int. See Section E.2 for writeStr and readLn.

E.4 Logic Gates

4 -1

x
x 1



0
1
0
1
1
1

x
x + 0



0
0
0
1
0
1
4 -2

x
y
x y
y x




0
0
0
0
0
1
0
0
1
0
0
0
1
1
1
1

x
y
x + y
y + x




0
0
0
0
0
1
1
1
1
0
1
1
1
1
1
1
4 -3

x
x 0



0
0
0
1
0
0

x
x + 1



0
1
1
1
1
1
4 -4

x
x
x 0



0
1
0
1
0
0

x
x
x + 1



0
1
1
1
0
1
4 -5

x
x
x 0



0
0
0
1
1
1

x
x
x + 1



0
0
0
1
1
1
4 -6

x
y
z
x (y + z)
x y + x z





0
0
0
0
0
0
0
1
0
0
0
1
0
0
0
0
1
1
0
0
1
0
0
0
0
1
0
1
1
1
1
1
0
1
1
1
1
1
1
1

x
y
z
x + y z
(x + y) (x + z)





0
0
0
0
0
0
0
1
0
0
0
1
0
0
0
0
1
1
1
1
1
0
0
1
1
1
0
1
1
1
1
1
0
1
1
1
1
1
1
1
4 -7

Using a truth table and letting y = x:

x
y = x
y



0
1
0
1
0
1
4 -9

Minterms:

PICT

4 -10

Minterms:

PICT

4 -11

The prime numbers correspond to the minterms m2, m3, m5, and m7. The minterms m10, m11, m12, m13, m14, m15 cannot occur so are marked “don’t care” on the Karnaugh map.

PICT

                      ′
F(w,x,y,z)  =  x ⋅z + x ⋅y
4 -15

2-bit “below” circuit.

x1
x0
y1
y0
F





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


PIC

E.5 Logic Circuits

5 -3

Referring to Figure 5.27 (page 404), we see that JK = 10 is the set (state = 1) input and JK = 01 is the reset (state = 0).

Enable = 0
Enable = 1
Current
Next
Next
n1
n0
n1
n0
J1
K1
J0
K0
n1
n0
J1
K1
J0
K0














0
0
0
0
0
1
0
1
0
1
0
1
1
0
0
1
0
1
0
1
1
0
1
0
1
0
0
1
1
0
1
0
1
0
0
1
1
1
1
0
1
0
1
1
1
1
1
0
1
0
0
0
0
1
0
1

This leads to the following equations for the inputs to the JK flip-flops (using “E” for “Enable”):

         ′  ′       ′             ′  ′          ′
J0  =   E ⋅n1 ⋅n0 + E ⋅n1 ⋅n0 + E ⋅n1 ⋅n0 + E ⋅n1 ⋅n0
K0  =   E′ ⋅n′1 ⋅n ′0 + E′ ⋅n1 ⋅n′0 + E ⋅n′1 ⋅n0 + E ⋅n1 ⋅n0
J1  =   E′ ⋅n1 ⋅n ′0 + E′ ⋅n1 ⋅n0 + E ⋅n′1 ⋅n0 + E ⋅n1 ⋅n′0
K   =   E′ ⋅n′ ⋅n ′+ E′ ⋅n′ ⋅n + E ⋅n′⋅n′ + E ⋅n ⋅n
  1         1   0      1   0      1  0       1  0

Simplify these equations using Karnaugh maps.

PICT    PICT

PICT    PICT

J0  =  E ′ ⋅n0 + E ⋅n′
         ′  ′      0
K0  =  E ′⋅n0 + E ⋅n1′     ′
J1  =  E  ⋅n1 + n1 ⋅n0 + E ⋅n1 ⋅n0
K1  =  E ′ ⋅n′1 + n′1 ⋅n′0 + E ⋅n1 ⋅n0
5 -4

Four-bit up counter.

PIC

E.6 Central Processing Unit

6 -3

The compiler will not use a register for the theInteger variable because the algorithm requires the address of this variable, and registers have no memory address.

6 -5

 
1/* 
2 * endian.c 
3 * Determines endianess. If endianess cannot be determined 
4 * from input value, defaults to "big endian" 
5 * Bob Plantz - 22 June 2009 
6 */ 
7 
8#include <stdio.h> 
9 
10int main(void) 
11{ 
12    unsigned char *ptr; 
13    int x, i, bigEndian; 
14 
15    ptr = (unsigned char *)&x; 
16 
17    printf("Enter a non-zero integer: "); 
18    scanf("%i", &x); 
19 
20    printf("You entered %#010x and it is stored\n", x); 
21    for (i = 0; i < 4; i++) 
22        printf("   %p: %02x\n", ptr + i, *(ptr + i)); 
23 
24    bigEndian = (*ptr == (unsigned char)(0xff & (x >> 24))) && 
25            (*(ptr + 1) == (unsigned char)(0xff & (x >> 16))) && 
26            (*(ptr + 2) == (unsigned char)(0xff & (x >> 8))) && 
27            (*(ptr + 3) == (unsigned char)(0xff & x)); 
28    if (bigEndian) 
29        printf("which is big endian.\n"); 
30    else 
31        printf("which is little endian.\n"); 
32 
33    return 0; 
34}
6 -6

 
1/* 
2 * endianReg.c 
3 * Stores user int in memory then copies to register var. 
4 * Use gdb to observe endianess. 
5 * Bob Plantz - 22 June 2009 
6 */ 
7 
8#include <stdio.h> 
9 
10int main(void) 
11{ 
12    int x; 
13    register int y; 
14 
15    printf("Enter an integer: "); 
16    scanf("%i", &x); 
17 
18    y = x; 
19    printf("You entered %i\n", y); 
20 
21    return 0; 
22}

When I ran this program with the input -1985229329, I got the results:

     (gdb) print &x
     $5 = (int *) 0x7ffff74f473c
     (gdb) x/4xb 0x7ffff74f473c
     0x7ffff74f473c: 0xef 0xcd 0xab 0x89
     (gdb) i r rcx
     rcx            0xffffffff89abcdef -1985229329
     (gdb) print x
     $6 = -1985229329
     (gdb)
   
which shows the value stored in rcx (used as the y variable) is in regular order, and the value store in memory (the x variable) is in little endian.

E.7 Programming in Assembly Language

7 -1

 
1# f.s 
2# Does nothing but return zero to caller. 
3# Bob Plantz - 22 June 2009 
4 
5        .text 
6        .globl  f 
7        .type   f, @function 
8f: 
9        pushq   %rbp            # save callers frame pointer 
10        movq    %rsp, %rbp      # establish ours 
11 
12        movl    $0, %eax        # return 0; 
13 
14        movq    %rbp, %rsp      # delete local vars. 
15        popq    %rbp            # restore callers frame pointer 
16        ret                     # return to caller
7 -2

 
1# g.s 
2# Does nothing but return to caller. 
3# Bob Plantz - 22 June 2009 
4 
5        .text 
6        .globl  g 
7        .type   g, @function 
8g: 
9        pushq   %rbp            # save callers frame pointer 
10        movq    %rsp, %rbp      # establish ours 
11 
12# A function that returns void has "garbage" in eax. 
13 
14        movq    %rbp, %rsp      # delete local vars. 
15        popq    %rbp            # restore callers frame pointer 
16        ret                     # return to caller
7 -3

 
1# h.s 
2# Does nothing but return 123 to caller. 
3# Bob Plantz - 22 June 2009 
4 
5        .text 
6        .globl  h 
7        .type   h, @function 
8h: 
9        pushq   %rbp            # save callers frame pointer 
10        movq    %rsp, %rbp      # establish ours 
11 
12        movl    $123, %eax      # return 123; 
13 
14        movq    %rbp, %rsp      # delete local vars. 
15        popq    %rbp            # restore callers frame pointer 
16        ret                     # return to caller
7 -4

 
1/* 
2 * checkRetNos.c 
3 * calls three assembly language functions and 
4 * prints their return numbers. 
5 * 
6 * Bob Plantz - 22 June 2009 
7 */ 
8 
9#include <stdio.h> 
10int one(); 
11int two(); 
12int three(); 
13 
14int main() 
15{ 
16    int x; 
17 
18    x = one(); 
19    printf("one returns %i, ", x); 
20 
21    x = two(); 
22    printf("two returns %i, and ", x); 
23 
24    x = three(); 
25    printf("three returns %i.\n", x); 
26 
27    return 0; 
28}
 
1# one.s 
2# returns 1 to calling function. 
3# Bob Plantz - 22 June 2009 
4 
5        .text 
6        .globl  one 
7        .type   one, @function 
8one: 
9        pushq   %rbp            # save callers base pointer 
10        movq    %rsp, %rbp      # establish ours 
11 
12        movl    $1, %eax        # return 1; 
13 
14        movq    %rbp, %rsp      # delete local vars. 
15        popq    %rbp            # restore callers base pointer 
16        ret                     # return to caller
 
1# two.s 
2# returns 2 to calling function. 
3# Bob Plantz - 22 June 2009 
4 
5        .text 
6        .globl  two 
7        .type   two, @function 
8two: 
9        pushq   %rbp            # save callers base pointer 
10        movq    %rsp, %rbp      # establish ours 
11 
12        movl    $2, %eax        # return 1; 
13 
14        movq    %rbp, %rsp      # delete local vars. 
15        popq    %rbp            # restore callers base pointer 
16        ret                     # return to caller
 
1# three.s 
2# returns 3 to calling function. 
3# Bob Plantz - 22 June 2009 
4 
5        .text 
6        .globl  three 
7        .type   three, @function 
8three: 
9        pushq   %rbp            # save callers base pointer 
10        movq    %rsp, %rbp      # establish ours 
11 
12        movl    $3, %eax        # return 3; 
13 
14        movq    %rbp, %rsp      # delete local vars. 
15        popq    %rbp            # restore callers base pointer 
16        ret                     # return to caller
7 -5

 
1/* 
2 * checkRetLtrs.c 
3 * calls three assembly language functions and 
4 * prints their return characters. 
5 * 
6 * Bob Plantz - 22 June 2009 
7 */ 
8 
9#include <stdio.h> 
10char el(); 
11char em(); 
12char en(); 
13 
14int main() 
15{ 
16    char letter; 
17 
18    letter = el(); 
19    printf("el returns %c, ", letter); 
20 
21    letter = em(); 
22    printf("en returns %c, and ", letter); 
23 
24    letter = en(); 
25    printf("em returns %c.\n", letter); 
26 
27    return 0; 
28}
 
1# el.s 
2# returns L to calling function. 
3# Bob Plantz - 22 June 2009 
4        .text 
5        .globl  el 
6        .type   el, @function 
7el: 
8        pushq   %rbp            # save callers base pointer 
9        movq    %rsp, %rbp      # establish ours 
10 
11        movl    $L, %eax       # return L; 
12 
13        movq    %rbp, %rsp      # delete local vars. 
14        popq    %rbp            # restore callers base pointer 
15        ret                     # return to caller
 
1# em.s 
2# returns M to calling function. 
3# Bob Plantz - 22 June 2009 
4        .text 
5        .globl  em 
6        .type   em, @function 
7em: 
8        pushq   %rbp            # save callers base pointer 
9        movq    %rsp, %rbp      # establish ours 
10 
11        movl    $M, %eax       # return M; 
12 
13        movq    %rbp, %rsp      # delete local vars. 
14        popq    %rbp            # restore callers base pointer 
15        ret                     # return to caller
 
1# en.s 
2# returns N to calling function. 
3# Bob Plantz - 22 June 2009 
4        .text 
5        .globl  en 
6        .type   en, @function 
7en: 
8        pushq   %rbp            # save callers base pointer 
9        movq    %rsp, %rbp      # establish ours 
10 
11        movl    $N, %eax       # return N; 
12 
13        movq    %rbp, %rsp      # delete local vars. 
14        popq    %rbp            # restore callers base pointer 
15        ret                     # return to caller
7 -6

The four characters are returned as a 4-byte word and then stored in memory by main. They are then written to standard out one character at a time. Storage order in memory is little endian, so the characters are displayed “backwards.”

 
1/* 
2 * fourLetterWord.c 
3 * calls a function to get a four letter word, then 
4 * prints it. 
5 * 
6 * Bob Plantz - 22 June 2009 
7 */ 
8 
9#include <unistd.h> 
10#include "retWord.h" 
11 
12int main() 
13{ 
14    int x; 
15    char endl = \n; 
16 
17    x = retWord(); 
18    write(STDOUT_FILENO, &x, 4); 
19 
20    write(STDOUT_FILENO, &endl, 1); 
21 
22    return 0; 
23}
 
1# retWord.s 
2# returns 4-letter word to calling function. 
3# Bob Plantz - 22 June 2009 
4        .text 
5        .globl  retWord 
6        .type   retWord, @function 
7retWord: 
8        pushq   %rbp            # save callers base pointer 
9        movq    %rsp, %rbp      # establish ours 
10 
11        movl    $0x61426339, %eax        # return "aBc9"; 
12 
13        movq    %rbp, %rsp      # delete local vars. 
14        popq    %rbp            # restore callers base pointer 
15        ret                     # return to caller

E.8 Program Data – Input, Store, Output

8 -2

 
1/* 
2 * stackPositive.c 
3 * implementation of push and pop stack operations in C 
4 * 
5 * Bob Plantz - 22 June 2009 
6 */ 
7 
8#include <stdio.h> 
9 
10int theStack[500]; 
11int *stackPointer = &theStack[0]; 
12 
13/* 
14 * precondition: 
15 *     stackPointer points to data element at top of stack 
16 * postcondtion: 
17 *     address in stackPointer is incremented by four 
18 *     data_value is stored at top of stack 
19 */ 
20void push(int data_value) 
21{ 
22    stackPointer++; 
23    *stackPointer = data_value; 
24} 
25 
26/* 
27 * precondition: 
28 *     stackPointer points to data element at top of stack 
29 * postcondtion: 
30 *     data element at top of stack is copied to *data_location 
31 *     address in stackPointer is decremented by four 
32 */ 
33void pop(int *data_location) 
34{ 
35    *data_location = *stackPointer; 
36    stackPointer--; 
37} 
38 
39int main(void) 
40{ 
41    int x = 12; 
42    int y = 34; 
43    int z = 56; 
44    printf("Start with the stack pointer at %p", (void *)stackPointer); 
45    printf(", and x = %i, y = %i, and z = %i\n", x, y, z); 
46 
47    push(x); 
48    push(y); 
49    push(z); 
50    x = 100; 
51    y = 200; 
52    z = 300; 
53    printf("Now the stack pointer is at %p", (void *)stackPointer); 
54    printf(", and x = %i, y = %i, and z = %i\n", x, y, z); 
55    pop(&z); 
56    pop(&y); 
57    pop(&x); 
58 
59    printf("And we end with the stack pointer at %p", (void *)stackPointer); 
60    printf(", and x = %i, y = %i, and z = %i\n", x, y, z); 
61 
62    return 0; 
63}
8 -3

Use gdb to examine the values in the rbp and rsp registers just before the first and just before the last instructions are executed.

8 -4

This exercise shows that the text strings and local variables are stored in different areas of memory.

8 -6

 
1# int2hex.s 
2# Prompts user to enter an integer, then displays its hex equivalent 
3# Bob Plantz - 22 June 2009 
4 
5# Stack frame 
6        .equ    anInt,-4 
7        .equ    localSize,-16 
8# Read only data 
9        .section  .rodata 
10prompt: 
11        .string "Enter an integer number: " 
12scanFormat: 
13        .string "%i" 
14printFormat: 
15        .string "%i = %x\n" 
16# Code 
17        .text                  # switch to text segment 
18        .globl  main 
19        .type   main, @function 
20main: 
21        pushq   %rbp           # save callers base pointer 
22        movq    %rsp, %rbp     # establish our base pointer 
23        addq    $localSize, %rsp  # for local variable 
24 
25        movl    $prompt, %edi  # address of prompt text string 
26        movl    $0, %eax       # no floating point args. 
27        call    printf         # invoke printf function 
28 
29        leaq    anInt(%rbp), %rsi  # place to store integer 
30        movl    $scanFormat, %edi  # address of scanf format string 
31        movl    $0, %eax       # no floating point args. 
32        call    scanf          # invoke scanf function 
33 
34        movl    anInt(%rbp), %edx   # the integer 
35        movl    anInt(%rbp), %esi   #    two copies 
36        movl    $printFormat, %edi  # address of printf text string 
37        movl    $0, %eax       # no floating point args. 
38        call    printf         # invoke printf function 
39 
40        movl    $0, %eax       # return 0 
41        movq    %rbp, %rsp     # delete local variables 
42        popq    %rbp           # restore callers base pointer 
43        ret                    # back to calling function
8 -7

 
1# assignSeveral.s 
2# Assigns values to four chars and four ints and prints them. 
3# Bob Plantz - 22 June 2009 
4 
5# Stack frame 
6        .equ    a,-1 
7        .equ    b,-2 
8        .equ    c,-3 
9        .equ    d,-4 
10        .equ    w,-8 
11        .equ    x,-12 
12        .equ    y,-16 
13        .equ    z,-20 
14        .equ    arg7,0 
15        .equ    arg8,8 
16        .equ    arg9,16 
17        .equ    localSize,-48 
18# Read only data 
19        .section  .rodata 
20format: 
21        .string "The values are %c, %i, %c, %i, %c, %i, %c, and %i\n" 
22# Code 
23       .text 
24       .globl  main 
25       .type   main, @function 
26main: 
27        pushq   %rbp             # save calling functions base pointer 
28        movq    %rsp, %rbp       # establish our base pointer 
29        addq    $localSize, %rsp # allocate memory for local variables 
30 
31        movb    $A, a(%rbp)    # initialize chars 
32        movb    $B, b(%rbp) 
33        movb    $C, c(%rbp) 
34        movb    $D, d(%rbp) 
35        movl    $12, w(%rbp)     # and ints 
36        movl    $34, x(%rbp) 
37        movl    $45, y(%rbp) 
38        movl    $67, z(%rbp) 
39 
40        movslq  z(%rbp), %rax    # load z 
41        movq    %rax, arg9(%rsp) # and place on stack 
42        movzbq  d(%rbp), %rax    # load d 
43        movq    %rax, arg8(%rsp) # place on stack 
44        movslq  y(%rbp), %rax    # load y 
45        movq    %rax, arg7(%rsp) # place on stack 
46        movl    y(%rbp), %r9d 
47        movzblc(%rbp), %r9d    # load args into regs. 
48        movl    x(%rbp), %r8d 
49        movzblb(%rbp), %ecx 
50        movl    w(%rbp), %edx 
51        movzbla(%rbp), %esi 
52        movl    $format, %edi    # format string 
53        movl  $0, %eax         # no floating point values 
54        call  printf 
55 
56        movq    %rbp, %rsp       # delete local variables 
57        popq    %rbp             # restore calling functions base pointer 
58        movl    $0, %eax         # return 0 
59        ret

E.9 Computer Operations

9 -1

Your numbers may differ.

instruction n bytes rax rsi rbp rsp






7f940f088a60 7fff24330778 0 7fff172a9618
pushq %rbp 1 7f940f088a60 7fff24330778 0 7fff172a9610
movl %rsp, %rbp 3 7f940f088a60 7fff24330778 7fff172a9610 7fff172a9610
movl $0xabcd1234,%esi 5 7f940f088a60 abcd1234 7fff172a9610 7fff172a9610
movl $0, %eax 5 0 abcd1234 7fff172a9610 7fff172a9610
movl %rbp, %rsp 3 0 abcd1234 7fff172a9610 7fff172a9610
popq %rbp 1 0 abcd1234 0 7fff172a9618
ret
9 -3

Comments have been added. Your results may vary depending on version changes in gcc.

 
1        .file  "addAndSubtract3.c" 
2        .section      .rodata 
3.LC0: 
4        .string"Enter two integers: " 
5.LC1: 
6        .string"%i %i" 
7.LC2: 
8        .string"sum = %i, difference = %i\n" 
9        .text 
10        .globlmain 
11        .type  main, @function 
12main: 
13        pushq  %rbp 
14        movq  %rsp, %rbp 
15        subq  $16, %rsp 
16        movl  $.LC0, %edi 
17        movl  $0, %eax 
18        call  printf 
19        leaq  -12(%rbp), %rdx 
20        leaq  -16(%rbp), %rax 
21        movq  %rax, %rsi 
22        movl  $.LC1, %edi 
23        movl  $0, %eax 
24        call  __isoc99_scanf 
25        movl  -16(%rbp), %eax   # load w 
26        movl  %eax, -8(%rbp)    # y = w; 
27        movl  -12(%rbp), %eax   # load x 
28        addl  %eax, -8(%rbp)    # y += x; 
29        movl  -16(%rbp), %eax   # load w 
30        movl  %eax, -4(%rbp)    # z = w; 
31        movl  -12(%rbp), %eax   # load x 
32        subl  %eax, -4(%rbp)    # z -= x; 
33        movl  -4(%rbp), %edx 
34        movl  -8(%rbp), %eax 
35        movl  %eax, %esi 
36        movl  $.LC2, %edi 
37        movl  $0, %eax 
38        call  printf 
39        movl  $0, %eax 
40        leave 
41        ret 
42        .size  main, .-main 
43        .ident"GCC: (Ubuntu/Linaro 4.7.0-7ubuntu3) 4.7.0" 
44        .section      .note.GNU-stack,"",@progbits
9 -4

The assembly language program in Listing 9.6 uses esi for the y variable and edx for the z variable. If there is overflow, the call to printf changes the contents of these registers. So when the results are displayed y and/or z are incorrect.

 
1# addAndSubtract3.s 
2# Gets two integers from user, then 
3# performs addition and subtraction 
4# Bob Plantz - 23 June 2009 
5# Stack frame 
6        .equ    w,-16 
7        .equ    x,-12 
8        .equ    y,-8 
9        .equ    z,-4 
10        .equ    localSize,-16 
11# Read only data 
12        .section  .rodata 
13prompt: 
14        .string "Enter two integers: " 
15getData: 
16        .string "%i %i" 
17display: 
18        .string "sum = %i, difference = %i\n" 
19warning: 
20        .string "Overflow has occurred.\n" 
21# Code 
22        .text 
23        .globl  main 
24        .type   main, @function 
25main: 
26        pushq   %rbp        # save callers base pointer 
27        movq    %rsp, %rbp  # establish our base pointer 
28        addq    $localSize, %rsp  # for local vars 
29 
30        movl    $prompt, %edi  # prompt user 
31        movl    $0, %eax       # no floats 
32        call    printf 
33 
34        leaq    x(%rbp), %rdx  # &x 
35        leaq    w(%rbp), %rsi  # &w 
36        movl    $getData, %edi # get user data 
37        movl    $0, %eax       # no floats 
38        call    scanf 
39 
40############################################################## 
41# These three instructions could replace the four that follow 
42# this sequence. They work because mov does not affect eflags. 
43# But changes in the code may introduce an instruction before 
44# the jno that does affect eflags, thus breaking the code. 
45#       movl    w(%rbp), %eax  # load w 
46#       addl    y(%rbp), %eax  # add y 
47#       movl    %eax, y(%rbp)  # y = w + x 
48############################################################## 
49        movl    w(%rbp), %eax  # load w 
50        movl    %eax, y(%rbp)  # y = w 
51        movl    x(%rbp), %eax  # load x 
52        addl    %eax, y(%rbp)  # y = w + x 
53        jno     nOver1         # skip warning if no OF 
54        movl    $warning, %edi #### changes edi 
55        movl    $0, %eax 
56        call    printf         #### may change several registers 
57nOver1: 
58        movl    w(%rbp), %eax  # load w 
59        movl    %eax, z(%rbp)  # z = w 
60        movl    x(%rbp), %eax  # load x 
61        subl    %eax, z(%rbp)  # z = w - x 
62        jno     nOver2         # skip warning if no OF 
63        movl    $warning, %edi 
64        movl    $0, %eax 
65        call    printf 
66nOver2: 
67        movl    z(%rbp), %edx  # load z 
68        movl    y(%rbp), %esi  # and y 
69        movl    $display, %edi # display results 
70        movl    $0, %eax       # no floats 
71        call    printf 
72 
73        movl    $0, %eax       # return 0 to OS 
74        movq    %rbp, %rsp     # restore stack pointer 
75        popq    %rbp           # restore callers base pointer 
76        ret
9 -7

GAS LISTING Exercise_9-6.s  page 1  
 
 
   1               # Exercise_9-6.s  
   2               # This is not a program. It is a group of  
   3               # instructions to hand-assemble.  
   4               # Bob Plantz - 27 June 2009  
   5                       .text  
   6                       .globl  main  
   7               main:  
   8 0000 55                pushq   %rbp  
   9 0001 4889E5            movq    %rsp, %rbp  
  10  
  11 0004 B9EFCDAB          movl    $0x89abcdef, %ecx     # a)  
  11      89  
  12 0009 66B8CDAB          movw    $0xabcd, %ax          # b)  
  13 000d B030              movb    $0x30, %al            # c)  
  14 000f B431              movb    $0x31, %ah            # d)  
  15 0011 4D89C7            movq    %r8, %r15             # e)  
  16 0014 4588CA            movb    %r9b, %r10b           # f)  
  17 0017 4589DC            movl    %r11d, %r12d          # g)  
  18 001a 48BEF42C          movq    $0x7fffec9b2cf4, %rsi # h)  
  18      9BECFF7F  
  18      0000  
  19  
  20 0024 B8000000          movl    $0, %eax  
  20      00  
  21 0029 4889EC            movq    %rbp, %rsp  
  22 002c 5D                popq    %rbp  
  23 002d C3                ret  
  24
_______________________________________________________________________________

9 -8

GAS LISTING Exercise_9-7.s  page 1  
 
 
   1               # Exercise_9-7.s  
   2               # This is not a program. It is a group of  
   3               # instructions to hand-assemble.  
   4               # Bob Plantz - 27 June 2009  
   5                       .text  
   6                       .globl  main  
   7               main:  
   8 0000 55                pushq   %rbp  
   9 0001 4889E5            movq    %rsp, %rbp  
  10  
  11 0004 81C1EFCD          addl    $0x89abcdef, %ecx  # a)  
  11      AB89  
  12 000a 6605CDAB          addw    $0xabcd, %ax       # b)  
  13 000e 0430              addb    $0x30, %al         # c)  
  14 0010 80C431            addb    $0x31, %ah         # d)  
  15 0013 4D01E7            addq    %r12, %r15         # e)  
  16 0016 664501C2          addw    %r8w, %r10w        # f)  
  17 001a 4400CE            addb    %r9b, %sil         # g)  
  18 001d 01F7              addl    %esi, %edi         # h)  
  19  
  20 001f B8000000          movl    $0, %eax  
  20      00  
  21 0024 4889EC            movq    %rbp, %rsp  
  22 0027 5D                popq    %rbp  
  23 0028 C3                ret  
  24
_______________________________________________________________________________
9 -9

GAS LISTING Exercise_9-8.s  page 1  
 
 
   1               # Exercise_9-8.s  
   2               # This is not a program. It is an experiment  
   3               # to determine the machine code for pushl.  
   4               # Bob Plantz - 27 June 2009  
   5                       .text  
   6                       .globl  main  
   7               main:  
   8 0000 55                pushq   %rbp  
   9 0001 4889E5            movq    %rsp, %rbp  
  10  
  11 0004 50        pushq   %rax  
  12 0005 51                pushq   %rcx  
  13 0006 52                pushq   %rdx  
  14 0007 53                pushq   %rbx  
  15 0008 56                pushq   %rsi  
  16 0009 57                pushq   %rdi  
  17 000a 4150              pushq   %r8  
  18 000c 4151              pushq   %r9  
  19 000e 4152              pushq   %r10  
  20 0010 4153              pushq   %r11  
  21 0012 4154              pushq   %r12  
  22 0014 4155              pushq   %r13  
  23 0016 4156              pushq   %r14  
  24 0018 4157              pushq   %r15  
  25  
  26 001a 415F              popq    %r15  
  27 001c 415E              popq    %r14  
  28 001e 415D              popq    %r13  
  29 0020 415C              popq    %r12  
  30 0022 415B              popq    %r11  
  31 0024 415A              popq    %r10  
  32 0026 4159              popq    %r9  
  33 0028 4158              popq    %r8  
  34 002a 5F                popq    %rdi  
  35 002b 5E                popq    %rsi  
  36 002c 5B                popq    %rbx  
  37 002d 5A                popq    %rdx  
  38 002e 59                popq    %rcx  
  39 002f 58        popq    %rax  
  40  
  41 0030 B8000000          movl    $0, %eax  
  41      00  
  42 0035 4889EC            movq    %rbp, %rsp  
  43 0038 5D                popq    %rbp  
  44 0039 C3                ret  
  45
_______________________________________________________________________________
9 -10

See solution to Exercise 9

9 -11

GAS LISTING Exercise_9-10.s  page 1  
 
 
   1               # Exercise_9-10.s  
   2               # This is not a program. I used the machine code from the  
   3               # listing to create Exercise 9-9.  
   4               # Uses a drill and kill approach to learning  
   5               # how to disassemble machine code  
   6               # Bob Plantz - 27 June 2009  
   7                       .text  
   8                       .globl  main  
   9               main:  
  10 0000 55                pushq   %rbp  
  11 0001 4889E5            movq    %rsp, %rbp  
  12  
  13               #a  
  14 0004 B0AB              movb    $0xab, %al  
  15 0006 B4CD              movb    $0xcd, %ah  
  16 0008 41B0EF            movb    $0xef, %r8b  
  17 000b 41B701            movb    $0x01, %r15b  
  18  
  19               #b  
  20 000e 40B723            movb    $0x23, %dil  
  21 0011 40B634            movb    $0x34, %sil  
  22 0014 B256              movb    $0x56, %dl  
  23 0016 B678              movb    $0x78, %dh  
  24  
  25               #c  
  26 0018 B83412CD          movl    $0xabcd1234, %eax  
  26      AB  
  27 001d BBABCD12          movl    $0x3412cdab, %ebx  
  27      34  
  28 0022 41B90000          movl    $0x0, %r9d  
  28      0000  
  29 0028 41BE7B00          movl    $0x7b, %r14d  
  29      0000  
  30  
  31               #d  
  32 002e 66B8CDAB          movw    $0xabcd, %ax  
  33 0032 66BBBACD          movw    $0xcdba, %bx  
  34 0036 66B93412          movw    $0x1234, %cx  
  35 003a 66BA2143          movw    $0x4321, %dx  
  36  
  37               #e  
  38 003e 88C4              movb    %al, %ah  
  39 0040 88C8              movb    %cl, %al  
  40 0042 8808              movb    %cl, (%rax)  
  41 0044 88480A            movb    %cl, 10(%rax)  
  42 0047 8A08              movb    (%rax), %cl  
  43 0049 8A480A            movb    10(%rax), %cl  
  44  
  45               #f  
  46 004c 89C3              movl    %eax, %ebx  
  47 004e 6689D8            movw    %bx, %ax  
  48 0051 4889CA            movq    %rcx, %rdx  
  49 0054 4589C6            movl    %r8d, %r14d  
  50  
  51               #g  
  52 0057 04AB              addb    $0xab, %al  
  53 0059 80C4CD            addb    $0xcd, %ah  
GAS LISTING Exercise_9-10.s  page 2  
 
 
  54 005c 80C3EF            addb    $0xef, %bl  
  55 005f 80C701            addb    $0x01, %bh  
  56  
  57               #h  
  58 0062 80C123            addb    $0x23, %cl  
  59 0065 80C534            addb    $0x34, %ch  
  60 0068 80C256            addb    $0x56, %dl  
  61 006b 80C678            addb    $0x78, %dh  
  62  
  63               #i  
  64 006e 053412CD          addl    $0xabcd1234, %eax  
  64      AB  
  65 0073 81C3ABCD          addl    $0x3412cdab, %ebx  
  65      1234  
  66 0079 81C1D4C3          addl    $0xa1b2c3d4, %ecx  
  66      B2A1  
  67 007f 81C2A1B2          addl    $0xd4c3b2a1, %edx  
  67      C3D4  
  68  
  69               #o  
  70 0085 05AB0000          addl    $0xab, %eax  
  70      00  
  71 008a 83C301            addl    $0x1, %ebx  
  72 008d 83C100            addl    $0x0, %ecx  
  73 0090 81C2FF00          addl    $0xff, %edx  
  73      0000  
  74  
  75               #k  
  76 0096 6605CDAB          addw    $0xabcd, %ax  
  77 009a 6681C3BA          addw    $0xcdba, %bx  
  77