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

Using truth tables:

x
x 1



0
1
0
1
1
1

x
x + 0



0
0
0
1
0
1

4 -2

Using truth tables:

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

Using truth tables:

x
x 0



0
0
0
1
0
0

x
x + 1



0
1
1
1
1
1

4 -4

Using truth tables:

x
x
x 0



0
1
0
1
0
0

x
x
x + 1



0
1
1
1
0
1

4 -5

Using truth tables:

x
x
x 0



0
0
0
1
1
1

x
x
x + 1



0
0
0
1
1
1

4 -6

Using truth tables:

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 402), 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      CD  
  78 009f 6681C134          addw    $0x1234, %cx  
  78      12  
  79 00a4 6681C221          addw    $0x4321, %dx  
  79      43  
  80  
  81               #l  
  82 00a9 6605AB00          addw    $0xab, %ax  
  83 00ad 6683C301          addw    $0x1, %bx  
  84 00b1 6683C100          addw    $0x0, %cx  
  85 00b5 6681C2FF          addw    $0xff, %dx  
  85      00  
  86  
  87               #m  
  88 00ba 00C4              addb    %al, %ah  
  89 00bc 4100C2            addb    %al, %r10b  
  90 00bf 00CA              addb    %cl, %dl  
  91 00c1 4500C1            addb    %r8b, %r9b  
  92  
  93               #n  
  94 00c4 01C3              addl    %eax, %ebx  
  95 00c6 6601D8            addw    %bx, %ax  
  96 00c9 4801CA            addq    %rcx, %rdx  
  97 00cc 4501C6            addl    %r8d, %r14d  
  98  
  99 00cf B8000000          movl    $0, %eax  
  99      00  
GAS LISTING Exercise_9-10.s  page 3  
 
 
 100 00d4 4889EC            movq    %rbp, %rsp  
 101 00d7 5D                popq    %rbp  
 102 00d8 C3                ret
_______________________________________________________________________________

E.10 Program Flow Constructs

10 -1

 






instruction n bytes offset total decimal





7462 2 62 64 +100





749a 2 9a 9c -100





0f8426010000 6 00000126 0000012c +300





0f84cefeffff 6 fffffece fffffed4 -300





10 -2

Looking at the listing file:

  18 0009 EB03              jmp     here1  
  19 000b 83F601            xorl    $1, %esi    # no jump, turn of bit 0  
  20               here1:  
  21 000e 488D0425          leaq    here2, %rax  
  21      00000000  
  

the second byte in the jmp here1 instruction is 03, which is the number of bytes to the here1 location.

Single-stepping through the program with gdb and examining the contents of rax, rip, and pointer shows that jmp *%rax and jmp *pointer use the full address, not just an offset.

10 -3

The program will probably crash. When the write function is called, it returns the number of characters written. Return values are placed in eax. Hence, the address is overwritten. In general, it is safer to use variables in the stack frame if their values must remain the same after another function is called.

10 -4

 
1# numerals.s 
2# Displays the numerals on screen 
3# Bob Plantz - 27 June 2009 
4# useful constant 
5        .equ    STDOUT,1 
6# stack frame 
7        .equ    theNumeral,-1 
8        .equ    localSize,-16 
9# read only data 
10        .section  .rodata 
11newline: 
12        .byte   \n 
13# code 
14        .text 
15        .globl  main 
16        .type   main, @function 
17main: 
18        pushq   %rbp             # save callers base pointer 
19        movq    %rsp, %rbp       # establish ours 
20        addq    $localSize, %rsp # local vars. 
21 
22        movb    $0, theNumeral(%rbp) # initial numeral 
23loop: 
24        movl    $1, %edx         # one character 
25        leaq    theNumeral(%rbp), %rsi # in this mem location 
26        movl    $STDOUT, %edi 
27        call    write 
28 
29        incb    theNumeral(%rbp) # next char 
30        cmpb    $9, theNumeral(%rbp) # over 9 yet? 
31        jbe     loop             # no, keep going 
32 
33 allDone: 
34        movl    $1, %edx         # do a newline for user 
35        movl    $newline, %esi 
36        movl    $STDOUT, %edi 
37        call    write 
38 
39        movl    $0, %eax        # return 0; 
40 
41        movq    %rbp, %rsp      # delete local vars. 
42        popq    %rbp            # restore callers base pointer 
43        ret                     # return to caller
10 -5

 
1# alphaUpper.s 
2# Displays the upper case alphabet on screen 
3# Bob Plantz - 27 June 2009 
4# useful constant 
5        .equ    STDOUT,1 
6# stack frame 
7        .equ    theLetter,-1 
8        .equ    localSize,-16 
9# read only data 
10        .section  .rodata 
11newline: 
12        .byte   \n 
13# code 
14        .text 
15        .globl  main 
16        .type   main, @function 
17main: 
18        pushq   %rbp             # save callers base pointer 
19        movq    %rsp, %rbp       # establish ours 
20        addq    $localSize, %rsp # local vars. 
21 
22        movb    $A, theLetter(%rbp) # initial alpha 
23loop: 
24        movl    $1, %edx         # one character 
25        leaq    theLetter(%rbp), %rsi # in this mem location 
26        movl    $STDOUT, %edi 
27        call    write 
28 
29        incb    theLetter(%rbp)  # next char 
30        cmpb    $Z, theLetter(%rbp) # over Z yet? 
31        jbe     loop             # no, keep going 
32 
33 allDone: 
34        movl    $1, %edx         # do a newline for user 
35        movl    $newline, %esi 
36        movl    $STDOUT, %edi 
37        call    write 
38 
39        movl    $0, %eax        # return 0; 
40 
41        movq    %rbp, %rsp      # delete local vars. 
42        popq    %rbp            # restore callers base pointer 
43        ret                     # return to caller
10 -6

 
1# alphaLower.s 
2# Displays the lower case alphabet on screen 
3# Bob Plantz - 27 June 2009 
4# useful constant 
5        .equ    STDOUT,1 
6# stack frame 
7        .equ    theLetter,-1 
8        .equ    localSize,-16 
9# read only data 
10        .section  .rodata 
11newline: 
12        .byte   \n 
13# code 
14        .text 
15        .globl  main 
16        .type   main, @function 
17main: 
18        pushq   %rbp             # save callers base pointer 
19        movq    %rsp, %rbp       # establish ours 
20        addq    $localSize, %rsp # local vars. 
21 
22        movb    $a, theLetter(%rbp) # initial alpha 
23loop: 
24        movl    $1, %edx         # one character 
25        leaq    theLetter(%rbp), %rsi # in this mem location 
26        movl    $STDOUT, %edi 
27        call    write 
28 
29        incb    theLetter(%rbp)  # next char 
30        cmpb    $z, theLetter(%rbp) # over z yet? 
31        jbe     loop             # no, keep going 
32 
33 allDone: 
34        movl    $1, %edx         # do a newline for user 
35        movl    $newline, %esi 
36        movl    $STDOUT, %edi 
37        call    write 
38 
39        movl    $0, %eax        # return 0; 
40 
41        movq    %rbp, %rsp      # delete local vars. 
42        popq    %rbp            # restore callers base pointer 
43        ret                     # return to caller
10 -7

 
1/* 
2 * whileLoop.c 
3 * While loop multiplication. 
4 * 
5 * Bob Plantz - 27 June 2009 
6 */ 
7 
8#include<stdio.h> 
9 
10int main () 
11{ 
12    int x, y, z; 
13    int i; 
14 
15    printf("Enter two integers: "); 
16    scanf("%i %i", &x, &y); 
17    z = x; 
18    i = 1; 
19    while (i < y) 
20    { 
21        z += x; 
22        i++; 
23    } 
24    printf("%i * %i = %i\n", x, y, z); 
25    return 0; 
26}

With version 4.7.0 of gcc and no optimization (-O0), they both use the same assembly language for the loop:

28        jmp    .L2 
29.L3: 
30        movl  -16(%rbp), %eax 
31        addl  %eax, -8(%rbp) 
32        addl  $1, -4(%rbp) 
33.L2: 
34        movl  -12(%rbp), %eax 
35        cmpl  %eax, -4(%rbp) 
36        jl    .L3
10 -8

After the program executes, the system prompt is displayed twice because the “return key” is still in the standard in buffer. This can be fixed by reading two characters.

 
1/* 
2 * yesNo1a.c 
3 * Prompts user to enter a y/n response. 
4 * 
5 * Bob Plantz - 27 June 2009 
6 */ 
7 
8#include <unistd.h> 
9 
10static char response[2]; 
11 
12int main(void) 
13{ 
14    register char *ptr; 
15 
16    ptr = "Save changes? "; 
17 
18    while (*ptr != \0) 
19    { 
20        write(STDOUT_FILENO, ptr, 1); 
21        ptr++; 
22    } 
23 
24    read (STDIN_FILENO, response, 2); 
25 
26    if (*response == y) 
27    { 
28        ptr = "Changes saved.\n"; 
29        while (*ptr != \0) 
30        { 
31            write(STDOUT_FILENO, ptr, 1); 
32            ptr++; 
33        } 
34    } 
35    else 
36    { 
37        ptr = "Changes discarded.\n"; 
38        while (*ptr != \0) 
39        { 
40            write(STDOUT_FILENO, ptr, 1); 
41            ptr++; 
42        } 
43    } 
44    return 0; 
45}
10 -10

 
1# others.s 
2# Displays all printable characters other than numerals 
3# and letters. 
4# Bob Plantz - 27 June 2009 
5# useful constants 
6        .equ    STDOUT,1 
7        .equ    SPACE,   # lowest printable character 
8        .equ    SQUIGGLE,~   # highest printable character 
9# stack frame 
10        .equ    theChar,-1 
11        .equ    localSize,-16 
12# read only data 
13        .section  .rodata 
14newline: 
15        .byte   \n 
16# code 
17        .text 
18        .globl  main 
19        .type   main, @function 
20main: 
21        pushq   %rbp             # save callers base pointer 
22        movq    %rsp, %rbp       # establish ours 
23        addq    $localSize, %rsp # local vars. 
24 
25        movb    $SPACE, theChar(%rbp) # initial char 
26loop: 
27        cmpb    $SQUIGGLE, theChar(%rbp)  # all chars? 
28        ja      allDone         # yes, were done 
29 
30        cmpb    $0, theChar(%rbp)  # numeral? 
31        jb      print           # no, print it 
32        cmpb    $9, theChar(%rbp) 
33        jbe     noPrint         # yes, dont print it 
34        cmpb    $A, theChar(%rbp)  # upper case? 
35        jb      print           # no, print it 
36        cmpb    $Z, theChar(%rbp) 
37        jbe     noPrint         # yes, dont print it 
38        cmpb    $a, theChar(%rbp)  # lower case? 
39        jb      print           # no, print it 
40        cmpb    $z, theChar(%rbp) 
41        jbe     noPrint 
42print: 
43        movl    $1, %edx        # one character 
44        leaq    theChar(%rbp), %rsi  # in this mem location 
45        movl    $STDOUT, %edi   # standard out 
46        call    write 
47noPrint: 
48        incb    theChar(%rbp)   # next char 
49        jmp     loop            # check at top of loop 
50 
51 allDone: 
52        movl    $1, %edx        # do a newline for user 
53        movl    $newline, %esi 
54        movl    $STDOUT, %edi 
55        call    write 
56 
57        movl    $0, %eax        # return 0; 
58 
59        movq    %rbp, %rsp      # delete local vars. 
60        popq    %rbp            # restore callers base pointer 
61        ret                     # return to caller
10 -11

 
1# incChars.s 
2# Prompts user to enter a text string, then changes each 
3# character to the next higher one. 
4# Bob Plantz - 27 June 2009 
5# useful constants 
6        .equ    STDIN,0 
7        .equ    STDOUT,1 
8        .equ    SPACE,       # lowest printable character 
9        .equ    SQUIGGLE,~   # highest printable character 
10# stack frame 
11        .equ    theString,-256 
12        .equ    localSize,-256 
13# read only data 
14        .section  .rodata 
15prompt: 
16        .string "Enter a string of characters: " 
17msg: 
18        .string "Incrementing each character: " 
19newline: 
20        .byte   \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 ours 
28        addq    $localSize, %rsp # local vars. 
29 
30        movl    $prompt, %esi   # prompt user 
31promptLup: 
32        cmpb    $0, (%esi)      # end of string? 
33        je      getString       # yes, get user input 
34        movl    $1, %edx        # no, one character 
35        movl    $STDOUT, %edi 
36        call    write 
37        incl    %esi            # next char 
38        jmp     promptLup       # check at top of loop 
39 
40getString: 
41        leaq    theString(%rbp), %rsi # place to put user input 
42        movl    $1, %edx        # one character 
43        movl    $STDIN, %edi 
44        call    read 
45readLup: 
46        cmpb    $\n, (%rsi)   # end of input? 
47        je      incChars        # yes, process the string 
48        incq    %rsi            # next char 
49        movl    $1, %edx        # one character 
50        movl    $STDIN, %edi 
51        call    read 
52        jmp     readLup         # check at top of loop 
53 
54incChars: 
55        movb    $0, (%rsi)      # null character for C string 
56        leaq    theString(%rbp), %rsi # pointer to the string 
57incLoop: 
58        cmpb    $0, (%rsi)      # end of string? 
59        je      doDisplay       # yes, display the results 
60        incb    (%rsi)          # change character 
61        cmpb    $SQUIGGLE, (%rsi) # did we go too far? 
62        jbe     okay            # no 
63        movb    $SPACE, (%rsi)  # yes, wrap to beginning 
64okay: 
65        incq    %rsi            # next char 
66        jmp     incLoop         # check at top of loop 
67 
68doDisplay: 
69        movl    $msg, %esi      # print message for user 
70dispLoop: 
71        cmpb    $0, (%esi)      # end of string? 
72        je      showString      # yes, show results 
73        movl    $1, %edx        # no, one character 
74        movl    $STDOUT, %edi 
75        call    write 
76        incl    %esi            # next char 
77        jmp     dispLoop        # check at top of loop 
78 
79showString: 
80        leaq    theString(%rbp), %rsi # pointer to the string 
81showLoop: 
82        cmpb    $0, (%rsi)      # end of string? 
83        je      allDone         # yes, get user input 
84        movl    $1, %edx        # no, one character 
85        movl    $STDOUT, %edi 
86        call    write 
87        incq    %rsi            # next char 
88        jmp     showLoop        # check at top of loop 
89 
90 allDone: 
91        movl    $1, %edx        # do a newline for user 
92        movl    $newline, %esi 
93        movl    $STDOUT, %edi 
94        call    write 
95 
96        movl    $0, %eax        # return 0; 
97        movq    %rbp, %rsp      # delete local vars. 
98        popq    %rbp            # restore callers base pointer 
99        ret                     # return to caller
10 -12

 
1# decChars.s 
2# Prompts user to enter a text string, then changes each 
3# character to the next lower one. 
4# Bob Plantz - 27 June 2009 
5# useful constants 
6        .equ    STDIN,0 
7        .equ    STDOUT,1 
8        .equ    SPACE,      # lowest printable character 
9        .equ    SQUIGGLE,~  # highest printable character 
10# stack frame 
11        .equ    theString,-256 
12        .equ    localSize,-256 
13# read only data 
14        .section  .rodata 
15prompt: 
16        .string "Enter a string of characters: " 
17msg: 
18        .string "Decrementing each character: " 
19newline: 
20        .byte   \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 ours 
28        addq    $localSize, %rsp # local vars. 
29 
30        movl    $prompt, %esi   # prompt user 
31promptLup: 
32        cmpb    $0, (%esi)      # end of string? 
33        je      getString       # yes, get user input 
34        movl    $1, %edx        # no, one character 
35        movl    $STDOUT, %edi 
36        call    write 
37        incl    %esi            # next char 
38        jmp     promptLup       # check at top of loop 
39 
40getString: 
41        leaq    theString(%rbp), %rsi # place to put user input 
42        movl    $1, %edx        # one character 
43        movl    $STDIN, %edi 
44        call    read 
45readLup: 
46        cmpb    $\n, (%rsi)   # end of input? 
47        je      decChars        # yes, process the string 
48        incq    %rsi            # next char 
49        movl    $1, %edx        # one character 
50        movl    $STDIN, %edi 
51        call    read 
52        jmp     readLup         # check at top of loop 
53 
54decChars: 
55        movb    $0, (%rsi)      # null character for C string 
56        leaq    theString(%rbp), %rsi # pointer to the string 
57decLoop: 
58        cmpb    $0, (%rsi)      # end of string? 
59        je      doDisplay       # yes, display the results 
60        decb    (%rsi)          # change character 
61        cmpb    $SPACE, (%rsi)  # did we go too far? 
62        jae     okay            # no 
63        movb    $SQUIGGLE, (%rsi) # yes, wrap to beginning 
64okay: 
65        incq    %rsi            # next char 
66        jmp     decLoop         # check at top of loop 
67 
68doDisplay: 
69        movl    $msg, %esi      # print message for user 
70dispLoop: 
71        cmpb    $0, (%esi)      # end of string? 
72        je      showString      # yes, show results 
73        movl    $1, %edx        # no, one character 
74        movl    $STDOUT, %edi 
75        call    write 
76        incl    %esi            # next char 
77        jmp     dispLoop        # check at top of loop 
78 
79showString: 
80        leaq    theString(%rbp), %rsi # pointer to the string 
81showLoop: 
82        cmpb    $0, (%rsi)      # end of string? 
83        je      allDone         # yes, get user input 
84        movl    $1, %edx        # no, one character 
85        movl    $STDOUT, %edi 
86        call    write 
87        incq    %rsi            # next char 
88        jmp     showLoop        # check at top of loop 
89 
90 allDone: 
91        movl    $1, %edx        # do a newline for user 
92        movl    $newline, %esi 
93        movl    $STDOUT, %edi 
94        call    write 
95 
96        movl    $0, %eax        # return 0; 
97        movq    %rbp, %rsp      # delete local vars. 
98        popq    %rbp            # restore callers base pointer 
99        ret                     # return to caller
10 -13

 
1# echoN.s 
2# Prompts user to enter a single character. 
3# The character is echoed. If it is a numeral, say N, 
4# it is echoed N+1 times 
5# Bob Plantz - 27 June 2009 
6# useful constants 
7        .equ    STDIN,0 
8        .equ    STDOUT,1 
9# stack frame 
10        .equ    count,-8 
11        .equ    response,-4 
12        .equ    localSize,-16 
13# read only data 
14        .section  .rodata 
15instruct: 
16        .ascii  "A single numeral, N, is echoed N+1 times, other characters " 
17        .asciz  "are\nechoed once. q ends program.\n\n" 
18prompt: 
19        .string "Enter a single character: " 
20msg: 
21        .string "You entered: " 
22bye: 
23        .string "End of program.\n" 
24newline: 
25        .byte   \n 
26# code 
27        .text 
28        .globl  main 
29        .type   main, @function 
30main: 
31        pushq   %rbp            # save callers base pointer 
32        movq    %rsp, %rbp      # establish ours 
33        addq    $localSize, %rsp  # local vars 
34 
35        movl    $instruct, %esi   # instruct user 
36instructLup: 
37        cmpb    $0, (%esi)      # end of string? 
38        je      runLoop         # yes, run program 
39        movl    $1, %edx        # no, one character 
40        movl    $STDOUT, %edi 
41        call    write 
42        incl    %esi            # next char 
43        jmp     instructLup     # check at top of loop 
44 
45runLoop: 
46        movl    $prompt, %esi   # prompt user 
47promptLup: 
48        cmpb    $0, (%esi)      # end of string? 
49        je      getChar         # yes, get user input 
50        movl    $1, %edx        # no, one character 
51        movl    $STDOUT, %edi 
52        call    write 
53        incl    %esi            # next char 
54        jmp     promptLup       # check at top of loop 
55 
56getChar: 
57        leaq    response(%rbp), %rsi # place to put user input 
58        movl    $2, %edx        # include newline 
59        movl    $STDIN, %edi 
60        call    read 
61 
62        movb    response(%rbp), %al   # get input character 
63        cmpb    $q, %al       # if q 
64        je      allDone         # end program 
65   # Otherwise, set up count loop 
66        movl    $1, count(%rbp) # assume not numeral 
67        cmpb    $0, %al       # check for numeral 
68        jb      echoLoop 
69        cmpb    $9, %al 
70        ja      echoLoop 
71        andl    $0xf, %eax      # numeral, convert to int 
72        incl    %eax            # echo N+1 times 
73        movl    %eax, count(%rbp) # save counter 
74echoLoop: 
75        movl    $msg, %esi      # pointer to the string 
76msgLoop: 
77        cmpb    $0, (%esi)      # end of string? 
78        je      doChar          # yes, show character 
79        movl    $1, %edx        # no, one character 
80        movl    $STDOUT, %edi 
81        call    write 
82        incl    %esi            # next char 
83        jmp     msgLoop         # check at top of loop 
84 
85doChar: 
86        movl    $1, %edx        # one character 
87        leaq    response(%rbp), %rsi # in this mem location 
88        movl    $STDOUT, %edi 
89        call    write 
90 
91        movl    $1, %edx        # and a newline 
92        movl    $newline, %esi 
93        movl    $STDOUT, %edi 
94        call    write 
95 
96        decl    count(%rbp)     # count-- 
97        jne     echoLoop        # continue if more to do 
98        jmp     runLoop         # else get next character 
99 
100allDone: 
101        movl    $bye, %esi      # ending message 
102doneLup: 
103        cmpb    $0, (%esi)      # end of string? 
104        je      cleanUp         # yes, get user input 
105        movl    $1, %edx        # no, one character 
106        movl    $STDOUT, %edi 
107        call    write 
108        incl    %esi            # next char 
109        jmp     doneLup         # check at top of loop 
110 
111cleanUp: 
112        movl    $0, %eax        # return 0; 
113        movq    %rbp, %rsp      # delete local vars. 
114        popq    %rbp            # restore callers base pointer 
115        ret                     # return to caller

E.11 Writing Your Own Functions

11 -3

 
1# helloworld.s 
2# Hello world program to test writeStr function 
3# Bob Plantz - 27 June 2009 
4 
5hiworld: 
6        .string "Hello, world!\n" 
7 
8        .text 
9        .globl  main 
10 
11main: 
12        pushq   %rbp            # save caller base pointer 
13        movq    %rsp, %rbp      # establish our base pointer 
14 
15        movl    $hiworld, %edi  # address of string to print 
16        call    writeStr        # write it 
17 
18        movl    $0, %eax        # return 0; 
19        movq    %rbp, %rsp      # delete local variables 
20        popq    %rbp            # restore caller base pointer 
21        ret
 
1# writeStr.s 
2# Writes a C-style text string to the standard output (screen). 
3# Bob Plantz - 27 June 2009 
4 
5# Calling sequence: 
6#       rdi <- address of string to be written 
7#       call    writestr 
8# returns number of characters written 
9 
10# Useful constant 
11        .equ    STDOUT,1 
12# Stack frame, showing local variables and arguments 
13        .equ    stringAddr,-16 
14        .equ    count,-4 
15        .equ    localSize,-16 
16 
17        .text 
18        .globl  writeStr 
19        .type   writeStr, @function 
20writeStr: 
21        pushq   %rbp             # save base pointer 
22        movq    %rsp, %rbp       # new base pointer 
23        addq    $localSize, %rsp # local vars. and arg. 
24 
25        movq    %rdi, stringAddr(%rbp)  # save string pointer 
26        movl    $0, count(%rbp)  # count = 0; 
27writeLoop: 
28        movq    stringAddr(%rbp), %rax # get current pointer 
29        cmpb    $0, (%rax)       # at end yet? 
30        je      done             # yes, all done 
31 
32        movl    $1, %edx         # no, write one character 
33        movq    %rax, %rsi       # points to current char 
34        movl    $STDOUT, %edi    # on the screen 
35        call    write 
36        incl    count(%rbp)      # count++; 
37        incl    stringAddr(%rbp) # stringAddr++; 
38        jmp     writeLoop        # and check for end 
39done: 
40        movl    count(%rbp), %eax    # return count 
41        movq    %rbp, %rsp      # restore stack pointer 
42        popq    %rbp            # restore base pointer 
43        ret                     # back to caller
11 -4

 
1# echoString.s 
2# Prompts user to enter a string, then echoes it. 
3# Bob Plantz - 27 June 2009 
4# stack frame 
5        .equ    theString,-256 
6        .equ    localSize,-256 
7# read only data 
8        .data 
9usrprmpt: 
10        .string "Enter a text string:\n" 
11usrmsg: 
12        .string "You entered:\n" 
13newline: 
14        .string "\n" 
15# code 
16        .text 
17        .globl  main 
18        .type   main, @function 
19main: 
20        pushq   %rbp              # save caller base pointer 
21        movq    %rsp, %rbp        # establish our base pointer 
22        addq    $localSize, %rsp  # local vars. 
23 
24        movl    $usrprmpt, %edi   # tell user what to do 
25        call    writeStr 
26 
27        leaq    theString(%rbp), %rdi # place for user response 
28        call    readLn 
29 
30        movl    $usrmsg, %edi     # echo for user 
31        call    writeStr 
32        leaq    theString(%rbp), %rdi 
33        call    writeStr 
34 
35        movl    $newline, %edi    # some formatting for user 
36        call    writeStr 
37 
38        movl    $0, %eax          # return 0; 
39        movq    %rbp, %rsp        # delete local variables 
40        popq    %rbp              # restore caller base pointer 
41        ret
 
1# readLnSimple.s 
2# Reads a line (through the ’\n character from standard input. Deletes 
3# the ’\n and creates a C-style text string. 
4# Bob Plantz - 27 June 2009 
5 
6# Calling sequence: 
7#       rdi <- address of place to store string 
8#       call    readLn 
9# returns number of characters read (not including NUL) 
10 
11# Useful constant 
12        .equ    STDIN,0 
13# Stack frame, showing local variables and arguments 
14        .equ    stringAddr,-16 
15        .equ    count,-4 
16        .equ    localSize,-16 
17 
18        .text 
19        .globl  readLn 
20        .type   readLn, @function 
21readLn: 
22        pushq   %rbp             # save base pointer 
23        movq    %rsp, %rbp       # new base pointer 
24        addq    $localSize, %rsp # local vars. and arg. 
25 
26        movq    %rdi, stringAddr(%rbp) # save string pointer 
27        movl    $0, count(%rbp)     # count = 0; 
28 
29        movl    $1, %edx       # read one character 
30        movq    stringAddr(%rbp), %rsi  # into storage area 
31        movl    $STDIN, %edi            # from keyboard 
32        call    read 
33readLoop: 
34        movq    stringAddr(%rbp), %rax # get pointer 
35        cmpb    $\n, (%rax)          # return key? 
36        je      endOfString            # yes, mark end of string 
37        incq    stringAddr(%rbp) # no, move pointer to next byte 
38        incl    count(%rbp)     # count++; 
39        movl    $1, %edx        # get another character 
40        movq    stringAddr(%rbp), %rsi  # into storage area 
41        movl    $STDIN, %edi            # from keyboard 
42        call    read 
43        jmp     readLoop        # and look at it 
44 
45endOfString: 
46        movq    stringAddr(%rbp), %rax # current pointer 
47        movb    $0, (%rax)             # mark end of string 
48 
49        movl    count(%rbp), %eax  # return count; 
50        movq    %rbp, %rsp      # restore stack pointer 
51        popq    %rbp            # restore base pointer 
52        ret                     # back to OS

See above for writeStr.

11 -5

Note: Some students will try to create a nested loop, the outer one being executed twice. But the display messages are not nearly as nice, unless the student uses some “goto” statements. In my opinion, two separate change case loops is better software engineering because it allows maximum flexibility in the user messages. The user will generally complain about what is seen on the screen, not the cleverness of the code.

 
1# changeCase.s 
2# Prompts user to enter a string, echoes it, changes case of alpha 
3# characters, displays them, changes them back, then displays result. 
4# Bob Plantz - 27 June 2009 
5 
6# Stack frame 
7        .equ    response,-256 
8        .equ    localSize,-256 
9        .data 
10usrprmpt: 
11        .string "Enter a text string:\n" 
12usrmsg: 
13        .string "You entered:\n" 
14chngmsg: 
15        .string "Changing the case gives:\n" 
16newline: 
17        .string "\n" 
18 
19        .text 
20        .globl  main 
21        .type   main, @function 
22main: 
23        pushq   %rbp              # save caller base pointer 
24        movq    %rsp, %rbp        # establish our base pointer 
25        addq    $localSize, %rsp  # local vars 
26 
27        movl    $usrprmpt, %edi   # tell user what to do 
28        call    writeStr 
29 
30        movl    $256, %esi        # max number of chars 
31        leaq    response(%rbp), %rdi # place to store them 
32        call    readLn 
33 
34        movl    $usrmsg, %edi     # echo for usr 
35        call    writeStr 
36 
37        leaq    response(%rbp), %rdi 
38        call    writeStr 
39 
40        movl    $newline, %edi    # some formatting for user 
41        call    writeStr 
42 
43        leaq    response(%rbp), %rax    # address of users text string 
44changeCaseLup: 
45        cmpb    $0, (%rax)        # end of string 
46        je      showChange        # yes, show what weve done 
47        cmpb    $A, (%rax)      # no, see if its an alpha character 
48        jb      notAlpha          # lower than A 
49        cmpb    $Z, (%rax)      # check if its upper case 
50        jbe     isAlpha           # it is 
51        cmpb    $a, (%rax)      # now check lower case range 
52        jb      notAlpha 
53        cmpb    $z, (%rax) 
54        ja      notAlpha 
55isAlpha: 
56        xorb    $0x20, (%rax)     # flip the case bit 
57notAlpha: 
58        incq    %rax              # next character 
59        jmp     changeCaseLup     # and check for end to string 
60 
61showChange: 
62        movl    $chngmsg, %edi    # tell user about it 
63        call    writeStr 
64 
65        leaq    response(%rbp), %rdi # show the changes 
66        call    writeStr 
67 
68        movl    $newline, %edi    # some formatting for user 
69        call    writeStr 
70 
71        leaq    response(%rbp), %rax    # address of users text string 
72restoreLup: 
73        cmpb    $0, (%rax)        # end of string 
74        je      showOrig          # yes, were back to original 
75        cmpb    $A, (%rax)      # no, see if its an alpha character 
76        jb      notLetter         # lower than A 
77        cmpb    $Z, (%rax)      # check if its upper case 
78        jbe     isLetter          # it is 
79        cmpb    $a, (%rax)      # now check lower case range 
80        jb      notLetter 
81        cmpb    $z, (%rax) 
82        ja      notLetter 
83isLetter: 
84        xorb    $0x20, (%rax)     # flip the case bit 
85notLetter: 
86        incq    %rax              # next character 
87        jmp     restoreLup        # and check for end to string 
88 
89showOrig: 
90        movl    $usrmsg, %edi    # show original version 
91        call    writeStr 
92 
93        leaq    response(%rbp), %rdi # should be restored 
94        call    writeStr 
95 
96        movl    $newline, %edi    # some formatting for user 
97        call    writeStr 
98 
99        movl    $0, %eax          # return 0; 
100        movq    %rbp, %rsp        # delete local variables 
101        popq    %rbp              # restore caller base pointer 
102        ret

See above for writeStr and readLn.

11 -6

 
1# echoString2.s 
2# Prompts user to enter a string, then echoes it. 
3# Bob Plantz - 27 June 2009 
4# stack frame 
5        .equ    theString,-256 
6        .equ    localSize,-256 
7# Length of the array. Do not make this larger than 255. 
8# I have used a small number to test readLn for removing 
9# extra characters from the keyboard buffer. 
10        .equ    arrayLngth,4 
11# read only data 
12        .data 
13usrprmpt: 
14        .string "Enter a text string:\n" 
15usrmsg: 
16        .string "You entered:\n" 
17newline: 
18        .string "\n" 
19# code 
20        .text 
21        .globl  main 
22main: 
23        pushq   %rbp              # save caller base pointer 
24        movq    %rsp, %rbp        # establish our base pointer 
25        addq    $localSize, %rsp  # local vars. 
26 
27        movl    $usrprmpt, %edi   # tell user what to do 
28        call    writeStr 
29 
30        movl    $arrayLngth, %esi # "length" of array 
31        leaq    theString(%rbp), %rdi # place for user response 
32        call    readLn 
33 
34        movl    $usrmsg, %edi     # echo for user 
35        call    writeStr 
36        leaq    theString(%rbp), %rdi 
37        call    writeStr 
38 
39        movl    $newline, %edi    # some formatting for user 
40        call    writeStr 
41 
42        movl    $0, %eax          # return 0; 
43        movq    %rbp, %rsp        # delete local variables 
44        popq    %rbp              # restore caller base pointer 
45        ret
 
1# readLn.s 
2# Reads a line (through the ’\n character from standard input. Deletes 
3# the ’\n and creates a C-style text string. 
4# Bob Plantz - 27 June 2009 
5 
6# Calling sequence: 
7#       rsi <- length of char array 
8#       rdi <- address of place to store string 
9#       call    readLn 
10# returns number of characters read (not including NUL) 
11 
12# Useful constant 
13        .equ    STDIN,0 
14# Stack frame, showing local variables and arguments 
15        .equ    maxLength,-24 
16        .equ    stringAddr,-16 
17        .equ    count,-4 
18        .equ    localSize,-32 
19 
20        .text 
21        .globl  readLn 
22        .type   readLn, @function 
23readLn: 
24        pushq   %rbp             # save base pointer 
25        movq    %rsp, %rbp       # new base pointer 
26        addq    $localSize, %rsp # local vars. and arg. 
27 
28        movq    %rsi, maxLength(%rbp)  # save max storage space 
29        movq    %rdi, stringAddr(%rbp) # save string pointer 
30 
31        movl    $0, count(%rbp)     # count = 0; 
32        subq    $1, maxLength(%rbp) # leave room for NUL char 
33 
34        movl    $1, %edx       # read one character 
35        movq    stringAddr(%rbp), %rsi  # into storage area 
36        movl    $STDIN, %edi            # from keyboard 
37        call    read 
38readLoop: 
39        movq    stringAddr(%rbp), %rax # get pointer 
40        cmpb    $\n, (%rax)          # return key? 
41        je      endOfString            # yes, mark end of string 
42        movl    count(%rbp), %eax      # current count 
43        cmpl    %eax, maxLength(%rbp)  # is callers array full? 
44        je      skipStore              # yes, store any more chars 
45 
46        incq    stringAddr(%rbp) # no, move pointer to next byte 
47        incl    count(%rbp)     # count++; 
48skipStore: 
49        movl    $1, %edx        # get another character 
50        movq    stringAddr(%rbp), %rsi  # into storage area 
51        movl    $STDIN, %edi            # from keyboard 
52        call    read 
53        jmp     readLoop        # and look at it 
54 
55endOfString: 
56        movq    stringAddr(%rbp), %rax # current pointer 
57        movb    $0, (%rax)             # mark end of string 
58 
59        movl    count(%rbp), %eax  # return count; 
60        movq    %rbp, %rsp      # restore stack pointer 
61        popq    %rbp            # restore base pointer 
62        ret                     # back to OS

See above for writeStr.

E.12 Bit Operations; Multiplication and Division

12 -1

 
1# binary2int.s 
2# Prompts the user to enter an integer in binary, then displays 
3# it in decimal. 
4# Bob Plantz - 12 June 2008 
5 
6# Stack frame 
7        .equ    theInt,-40 
8        .equ    buffer,-36 
9        .equ    localSize,-48 
10# Read only data 
11        .section  .rodata 
12prompt: 
13        .asciz  "Please enter an integer in binary: " 
14displayFmt: 
15        .asciz  "In decimal: %d\n" 
16# Code 
17        .text 
18        .globl  main 
19        .type   main, @function 
20main: 
21        pushq   %rbp             # save frame pointer 
22        movq    %rsp, %rbp       # new frame pointer 
23        addq    $localSize, %rsp # local vars. 
24 
25# Tell user what to do. 
26        movl    $prompt, %edi    # prompt user 
27        call    writeStr 
28 
29# Get binary number 
30        movl   $36, %esi        # max number of chars 
31        leaq    buffer(%rbp), %rax # place for user input 
32        movq    %rax, %rdi 
33        call    readLn           # get user input string 
34 
35# convert text string from zeros and ones to int format 
36        leaq    buffer(%rbp), %rdi  # start of string 
37        movl    $0, %esi         # use for int 
38convertloop: 
39        movb    (%rdi), %al      # get char 
40        cmpb    $0, %al          # null char? 
41        je      done_convert     # yes, done with conversion 
42        andb    $0x0f, %al       # no, convert char to 8-bit byte 
43        shll    $1, %esi         # make room for it 
44        orb     %al, %sil        # add it in 
45        incq    %rdi             # next char 
46        jmp     convertloop      # and do the next one 
47done_convert: 
48        movl    %esi, theInt(%rbp)  # store result 
49 
50# display in decimal 
51        movl    theInt(%rbp), %esi # int to display 
52        movl    $displayFmt, %edi  # format string 
53        movl    $0, %eax 
54        call    printf 
55 
56        movl    $0, %eax        # return 0 
57        movq    %rbp, %rsp      # restore stack pointer 
58        popq    %rbp            # restore frame pointer 
59        ret                     # back to OS

See Section E.11 for writeStr and readLn.

12 -2

 
1# int2binary.s 
2# Converts decimal int to binary 
3# Bob Plantz - 27 June 2009 
4 
5# Stack frame 
6        .equ    myInt,-44 
7        .equ    counter,-40 
8        .equ    buffer,-36 
9        .equ    localSize,-48 
10# Read only data 
11        .section  .rodata 
12prompt: 
13        .string "Enter an integer: " 
14format: 
15        .string "%i" 
16msg1: 
17        .string "The stored number is " 
18msg2: 
19        .string " in binary.\n" 
20# Code 
21        .text 
22        .globl  main 
23        .type   main, @function 
24main: 
25        pushq   %rbp            # save frame pointer 
26        movq    %rsp, %rbp      # new frame pointer 
27        addq    $localSize, %rsp  # local vars. 
28 
29        movl    $prompt, %edi   # prompt user 
30        call    writeStr 
31        leaq    myInt(%rbp), %rsi # get users int 
32        movl    $format, %edi 
33        movl    $0, %eax 
34        call    scanf 
35 
36# Generate text string of ones and zeros 
37        leaq    buffer(%rbp), %rax  # place for text string 
38        movl    $32, counter(%rbp)  # 32 bits 
39convertloop: 
40        shll    $1, myInt(%rbp) # move high order bit to CF 
41        jnc     zero            # its zero 
42        movb    $1, (%rax)    # one character 
43        jmp     cont            # go on 
44zero: 
45        movb    $0, (%rax)    # zero character 
46cont: 
47        incq    %rax            # next char position 
48        decl    counter(%rbp)   # counter-- 
49        jg      convertloop     # keep going until counter == 0 
50 
51        movb    $0, (%rax)      # store NULL 
52 
53# display in binary 
54        movl    $msg1, %edi     # nice message for user 
55        call    writeStr 
56 
57        leaq    buffer(%rbp), %rdi # address of our string 
58        call    writeStr 
59 
60        movl    $msg2, %edi     # nice message for user 
61        call    writeStr 
62 
63        movl    $0, %eax        # return 0 
64        movq    %rbp, %rsp      # restore stack pointer 
65        popq    %rbp            # restore frame pointer 
66        ret                     # back to OS

See Section E.11 for writeStr.

12 -3

 
1# multiply.s 
2# Gets two 16-bit integers from user and computes their product. 
3# Bob Plantz - 27 June 2009 
4 
5# Stack frame 
6        .equ    multiplier,-8 
7        .equ    multiplicand,-4 
8        .equ    localSize,-16 
9# Read only data 
10        .section  .rodata 
11prompt: 
12        .string "Enter an integer (0 - 65535): " 
13printformat: 
14        .string "%hu times %hu = %u\n" 
15scanformat: 
16        .string "%hu" 
17# Code 
18        .text 
19        .globl  main 
20        .type   main, @function 
21main: 
22        pushq   %rbp              # save frame pointer 
23        movq    %rsp, %rbp        # new frame pointer 
24        addq    $localSize, %rsp  # local vars. 
25 
26# prompt user 
27        movl    $prompt, %edi     # message address 
28        movl    $0, %eax 
29        call    printf 
30 
31# get first integer 
32        leaq    multiplicand(%rbp), %rsi  # place to store it 
33        movl    $scanformat, %edi # scanf formatting string 
34        movl    $0, %eax 
35        call    scanf 
36 
37# get second integer 
38        movl    $prompt, %edi     # message address 
39        movl    $0, %eax 
40        call    printf 
41 
42        leaq    multiplier(%rbp), %rsi  # place to store it 
43        movl    $scanformat, %edi # scanf formatting string 
44        movl    $0, %eax 
45        call    scanf 
46 
47# now multiply them 
48        movw    multiplier(%rbp), %si  # pass by value 
49        movw    multiplicand(%rbp), %di 
50        call    mul16 
51 
52# at this point, the 32-bit result is in eax 
53        movl    %eax, %ecx         # result 
54        movl    multiplier(%rbp), %edx   # one number 
55        movl    multiplicand(%rbp), %esi # other number 
56        movl    $printformat, %edi # printf formatting string 
57        movl    $0, %eax 
58        call    printf 
59 
60        movl    $0, %eax        # return 0 
61        movq    %rbp, %rsp      # restore stack pointer 
62        popq    %rbp            # restore base pointer 
63        ret                     # back to OS
 
1# mul16.s 
2# Multiplies two 16-bit integers and returns 32-bit result 
3# Bob Plantz - 27 June 2009 
4 
5# Calling sequence 
6#       si <- multiplier 
7#       di <- multiplicand 
8#       call mul16 
9#Code 
10        .text 
11        .globl  mul16 
12        .type   mul16, @function 
13mul16: 
14        pushq   %rbp            # save frame pointer 
15        movq    %rsp, %rbp      # new frame pointer 
16 
17        movw    %si, %ax        # move for multiply 
18        mulw    %di 
19 
20        sal     $16, %edx       # shift high-order part of answer 
21                                # into high-order part of the register 
22        andl    $0xffff, %eax   # make sure high-order part of eax is clear 
23        orl     %edx, %eax      # make 32-bit result for return 
24 
25        movq    %rbp, %rsp      # restore stack pointer 
26        popq    %rbp            # restore frame pointer 
27        ret                     # back to caller
12 -4

 
1# divide.s 
2# Gets two 32-bit integers from user and computes quotient 
3# of the first divided by the second. 
4# Bob Plantz - 27 June 2009 
5 
6# Stack frame 
7        .equ    divisor,-8 
8        .equ    dividend,-4 
9        .equ    localSize,-16 
10# Read only data 
11        .section  .rodata 
12prompt: 
13        .asciz  "Enter an integer (0 - 4294967295): " 
14printformat: 
15        .asciz  "%u div %u = %u\n" 
16scanformat: 
17        .asciz  "%u" 
18# Code 
19        .text 
20        .globl  main 
21        .type   main, @function 
22main: 
23        pushq   %rbp            # save frame pointer 
24        movq    %rsp, %rbp      # new frame pointer 
25        addq    $divisor, %rsp  # local vars. 
26 
27# prompt user 
28        movl    $prompt, %edi   # message address 
29        movl    $0, %eax 
30        call    printf 
31 
32# get first integer 
33        leaq    dividend(%rbp), %rsi  # place to store it 
34        movl    $scanformat, %edi     # scanf formatting string 
35        movl    $0, %eax 
36        call    scanf 
37 
38# get second integer 
39        movl    $prompt, %edi   # message address 
40        movl    $0, %eax 
41        call    printf 
42 
43        leaq    divisor(%rbp), %rsi  # place to store it 
44        movl    $scanformat, %edi    # scanf formatting string 
45        movl    $0, %eax 
46        call    scanf 
47 
48# now divide them 
49        movl    divisor(%rbp), %esi  # pass by value 
50        movl    dividend(%rbp), %edi 
51        call    div32 
52 
53# at this point, the 32-bit result is in eax 
54        movl    %eax, %ecx     # result 
55        movl    divisor(%rbp), %edx  # numerator 
56        movl    dividend(%rbp), %esi # denominator 
57        movl    $printformat, %edi   # printf formatting string 
58        movl    $0, %eax 
59        call    printf 
60 
61        movl    $0, %eax        # return 0 
62        movq    %rbp, %rsp      # restore stack pointer 
63        popq    %rbp            # restore frame pointer 
64        ret                     # back to OS
 
1# div32.s 
2# divides two 32-bit integers and returns 32-bit quotient 
3# Bob Plantz - 27 June 2009 
4 
5# Calling sequence 
6#       esi <- divisor 
7#       edi <- dividend 
8#       call div32 
9# Code 
10        .text 
11        .globl  div32 
12        .type   div32, @function 
13div32: 
14        pushq   %rbp            # save base pointer 
15        movq    %rsp, %rbp      # new base pointer 
16 
17        movl    $0, %edx        # clear for divide 
18        movl    %edi, %eax 
19        divl    %esi            # div is in eax 
20 
21        movq    %rbp, %rsp      # restore stack pointer 
22        popq    %rbp            # restore base pointer 
23        ret                     # return quotient
12 -5

 
1# modulo.s 
2# Gets two 32-bit integers from user and computes remainder 
3# of the first divided by the second. 
4# Bob Plantz - 27 June 2009 
5 
6# Stack frame 
7        .equ    divisor,-8 
8        .equ    dividend,-4 
9        .equ    localSize,-16 
10# Read only data 
11        .section  .rodata 
12prompt: 
13        .asciz  "Enter an integer (0 - 4294967295): " 
14printformat: 
15        .asciz  "%u mod %u = %u\n" 
16scanformat: 
17        .asciz  "%u" 
18# Code 
19        .text 
20        .globl  main 
21        .type   main, @function 
22main: 
23        pushq   %rbp            # save frame pointer 
24        movq    %rsp, %rbp      # new frame pointer 
25        addq    $localSize, %rsp  # local vars. 
26 
27# prompt user 
28        movl    $prompt, %edi   # message address 
29        movl    $0, %eax 
30        call    printf 
31 
32# get first integer 
33        leaq    dividend(%rbp), %rsi  # place to store it 
34        movl    $scanformat, %edi     # scanf formatting string 
35        movl    $0, %eax 
36        call    scanf 
37 
38# get second integer 
39        movl    $prompt, %edi   # message address 
40        movl    $0, %eax 
41        call    printf 
42 
43        leaq    divisor(%rbp), %rsi  # place to store it 
44        movl    $scanformat, %edi    # scanf formatting string 
45        movl    $0, %eax 
46        call    scanf 
47 
48# now divide them 
49        movl    divisor(%rbp), %esi  # pass by value 
50        movl    dividend(%rbp), %edi 
51        call    div32 
52 
53# at this point, the 32-bit result is in eax 
54        movl    %eax, %ecx     # result 
55        movl    divisor(%rbp), %edx  # numerator 
56        movl    dividend(%rbp), %esi # denominator 
57        movl    $printformat, %edi   # printf formatting string 
58        movl    $0, %eax 
59        call    printf 
60 
61        movl    $0, %eax        # return 0 
62        movq    %rbp, %rsp      # restore stack pointer 
63        popq    %rbp            # restore frame pointer 
64        ret                     # back to OS
 
1# mod32.s 
2# divides two 32-bit integers and returns 32-bit remainder 
3# Bob Plantz - 27 June 2009 
4 
5# Calling sequence 
6#       esi <- divisor 
7#       edi <- dividend 
8#       call div32 
9# Code 
10        .text 
11        .globl  div32 
12        .type   div32, @function 
13div32: 
14        pushq   %rbp            # save base pointer 
15        movq    %rsp, %rbp      # new base pointer 
16 
17        movl    $0, %edx        # clear for divide 
18        movl    %edi, %eax 
19        divl    %esi            # remainder is in edx 
20        movl    %edx, %eax      # return remainder 
21 
22        movq    %rbp, %rsp      # restore stack pointer 
23        popq    %rbp            # restore base pointer 
24        ret                     # return quotient
12 -6

 
1# decimal2unt.s 
2# Prompts the user to enter an integer in decimal, then converts 
3# it to int format. 
4# Bob Plantz - 27 June 2009 
5 
6# Constant 
7        .equ    buffSize,12 
8 
9# Stack frame 
10        .equ    buffer,-16 
11        .equ    theInt,-4 
12        .equ    localSize,-16 
13 
14# Read only data 
15        .section  .rodata 
16prompt: 
17        .asciz  "Please enter an integer in decimal: " 
18format: 
19        .asciz  "You entered %i\n" 
20 
21# Code 
22        .text 
23        .globl  main 
24        .type   main, @function 
25main: 
26        pushq   %rbp              # save frame pointer 
27        movq    %rsp, %rbp        # new frame pointer 
28        addq    $localSize, %rsp  # local vars. 
29 
30# Tell user what to do. 
31        movq    $prompt, %rdi     # prompt user 
32        call    writeStr 
33 
34# Get decimal number 
35        movl    $buffSize, %esi   # max number of chars 
36        leaq    buffer(%rbp), %rdi  # place for user input 
37        call    readLn            # get user input string 
38 
39# convert the string to int format 
40        leaq    theInt(%rbp), %rsi   # place to store the int 
41        leaq    buffer(%rbp), %rdi   # users string 
42        call    dec2uInt 
43 
44        movl    theInt(%rbp), %esi   # display results 
45        movq    $format, %rdi 
46        movl    $0, %eax 
47        call    printf 
48 
49        movl    $0, %eax        # return 0 
50        movq    %rbp, %rsp      # restore stack pointer 
51        popq    %rbp            # restore base pointer 
52        ret                     # back to OS
 
1# dec2uInt.s 
2# Converts string of numerals to decimal unsigned int 
3# Bob Plantz - 13 June 2009 
4 
5# Calling sequence 
6#       rsi <- address of place to store the int 
7#       rdi <- address of string 
8#       call dec2uInt 
9#       returns 0 
10# Code 
11        .text 
12        .globl  dec2uInt 
13        .type   dec2uInt, @function 
14dec2uInt: 
15        pushq   %rbp            # save caller frame ptr 
16        movq    %rsp, %rbp      # our stack frame 
17 
18        movl    $0, %eax        # subtotal = 0 
19loop: 
20        movb    (%rdi), %cl     # get current character 
21        cmpb    $0, %cl         # end of string? 
22        je      done            # yes, all done 
23        andl    $0xf, %ecx      # no, convert char to int 
24        imull   $10, %eax       # 10 x subtotal 
25        addl    %ecx, %eax      # add current int to subtotal 
26        incq    %rdi            # move pointer 
27        jmp     loop            # and check again 
28done: 
29        movl    %eax, (%rsi)    # store the int 
30 
31        movl    $0, %eax        # return 0 
32        movq    %rbp, %rsp      # delete local vars 
33        popq    %rbp            # restore caller frame ptr 
34        ret

See Section E.11 for writeStr and readLn.

12 -7

 
1# addConstant.s 
2# Prompts the user to enter an integer in decimal, converts 
3# it to int format, adds a constant, then displays result. 
4# Bob Plantz - 28 June 2009 
5 
6# useful constant 
7theConstant = 12345 
8 
9# Stack frame 
10        .equ    theInt,-16 
11        .equ    buffer,-12 
12        .equ    localSize,-16 
13# Read only data 
14        .section  .rodata 
15prompt: 
16        .asciz  "Please enter an integer in decimal: " 
17msg: 
18        .asciz  "The result is: " 
19endl: 
20        .asciz  "\n" 
21# Code 
22        .text 
23        .globl  main 
24        .type   main, @function 
25main: 
26        pushq   %rbp             # save frame pointer 
27        movq    %rsp, %rbp       # new frame pointer 
28        addq    $localSize, %rsp # local vars. 
29 
30# Tell user what to do. 
31        movl    $prompt, %edi    # prompt user 
32        call    writeStr 
33 
34# Get decimal number 
35        movl    $12, %esi        # allow up to 11 chars 
36        leaq    buffer(%rbp), %rdi # place for user input 
37        call    readLn           # get user input string 
38 
39# convert the string to int format 
40        leaq    theInt(%rbp), %rsi # place to store the int 
41        leaq    buffer(%rbp), %rdi # users string 
42        call    dec2uInt 
43 
44# add the constant 
45        addl    $theConstant, theInt(%rbp) 
46 
47# convert the int to string format 
48        movl    theInt(%rbp), %esi  # the result 
49        leaq    buffer(%rbp), %rdi 
50        call    uInt2dec         # do conversion 
51 
52# now display for user 
53        movl    $msg, %edi       # nice message for user 
54        call    writeStr 
55 
56        leaq    buffer(%rbp), %rdi 
57        call    writeStr 
58 
59        movl    $endl, %edi      # some formatting 
60        call    writeStr 
61 
62        movl    $0, %eax         # return 0 
63        movq    %rbp, %rsp       # restore stack pointer 
64        popq    %rbp             # restore frame pointer 
65        ret                      # back to OS
 
1# uInt2dec.s 
2# Converts unsigned int to corresponding unsigned decimal string 
3# Bob Plantz - 13 June 2009 
4 
5# Calling sequence 
6#       esi <- value of the int 
7#       rdi <- address of string 
8#       call uInt2dec 
9#       returns zero 
10 
11# Stack frame 
12        .equ    array,-12 
13        .equ    localSize,-16 
14# Read only data 
15        .section  .rodata 
16ten:    .long   10 
17# Code 
18        .text 
19        .globl  uInt2dec 
20        .type   uInt2dec, @function 
21uInt2dec: 
22        pushq   %rbp              # save callers frame ptr 
23        movq    %rsp, %rbp        # our stack frame 
24        addq    $localSize, %rsp  # local vars. 
25 
26        leaq    array(%rbp), %rcx # ptr to local array 
27        movb    $0, (%rcx)        # null byte 
28 
29        movl    %esi, %eax        # the number to conv. 
30charLup: 
31        movl    $0, %edx          # high-order = 0 
32        divl    ten               # divide by ten 
33        orb     $0x30, %dl        # convert to ascii 
34        incq    %rcx              # next location 
35        movb    %dl, (%rcx)       # store the character 
36        cmpl    $0, %eax          # anything left? 
37        jne     charLup           # yes, do it 
38 
39copyLup: 
40        cmpb    $0, (%rcx)        # NUL char? 
41        je      allDone           # yes, copy it 
42        movb    (%rcx), %dl       # get achar 
43        movb    %dl, (%rdi)       # store it 
44        incq    %rdi              # move pointers 
45        decq    %rcx 
46        jmp     copyLup           # and check again 
47 
48allDone: 
49        movb    (%rcx), %dl       # get NUL char 
50        movb    %dl, (%rdi)       # and store it 
51        movl    $0, %eax          # return count; 
52 
53        movq    %rbp, %rsp        # delete local vars. 
54        popq    %rbp              # restore caller frame ptr 
55        ret

See Section E.11 for writeStr and readLn.

12 -8

 
1# addConstant2.s 
2# Prompts the user to enter an integer in decimal, converts 
3# it to int format, adds a constant, then displays result. 
4# Bob Plantz - 28 June 2009 
5 
6# useful constant 
7theConstant = -12345 
8 
9# Stack frame 
10        .equ    theInt,-16 
11        .equ    buffer,-12 
12        .equ    localSize,-16 
13# Read only data 
14        .section  .rodata 
15prompt: 
16        .asciz  "Please enter an integer in decimal: " 
17msg: 
18        .asciz  "The result is: " 
19endl: 
20        .asciz  "\n" 
21# Code 
22        .text 
23        .globl  main 
24        .type   main, @function 
25main: 
26        pushq   %rbp             # save frame pointer 
27        movq    %rsp, %rbp       # new frame pointer 
28        addq    $localSize, %rsp # local vars. 
29 
30# Tell user what to do. 
31        movl    $prompt, %edi    # prompt user 
32        call    writeStr 
33 
34# Get decimal number 
35        movl    $12, %esi        # allow up to 11 chars 
36        leaq    buffer(%rbp), %rdi # place for user input 
37        call    readLn           # get user input string 
38 
39# convert the string to int format 
40        leaq    theInt(%rbp), %rsi # place to store the int 
41        leaq    buffer(%rbp), %rdi # users string 
42        call    dec2sInt 
43 
44# add the constant 
45        addl    $theConstant, theInt(%rbp) 
46 
47# convert the int to string format 
48        movl    theInt(%rbp), %esi  # the result 
49        leaq    buffer(%rbp), %rdi 
50        call    sInt2dec         # do conversion 
51 
52# now display for user 
53        movl    $msg, %edi       # nice message for user 
54        call    writeStr 
55 
56        leaq    buffer(%rbp), %rdi 
57        call    writeStr 
58 
59        movl    $endl, %edi      # some formatting 
60        call    writeStr 
61 
62        movl    $0, %eax         # return 0 
63        movq    %rbp, %rsp       # restore stack pointer 
64        popq    %rbp             # restore frame pointer 
65        ret                      # back to OS
 
1# dec2sInt.s 
2# Converts string of numerals to decimal int, signed version 
3# Bob Plantz - 13 June 2009 
4 
5# Calling sequence 
6#       rsi <- address of place to store the int 
7#       rdi <- address of string 
8#       call dec2sInt 
9#       returns 0 
10 
11# Stack frame 
12        .equ    negFlag,-4 
13        .equ    localSize,-16 
14# Code 
15        .text 
16        .globl  dec2sInt 
17        .type   dec2sInt, @function 
18dec2sInt: 
19        pushq   %rbp            # save caller frame ptr 
20        movq    %rsp, %rbp      # our stack frame 
21        addq    $localSize, %rsp  # space for local var 
22 
23        movl    $0, negFlag(%rbp) # assume false 
24 
25        cmpb    $-, (%rdi)    # minus sign? 
26        jne     checkPlus       # no, check for plus sign 
27        movl    $1, negFlag(%rbp) # negFlag = true; 
28        incq    %rdi            # skip minus sign 
29        jmp     doIt            # and do the conversion 
30checkPlus: 
31        cmpb    $+, (%rdi)    # plus sign? 
32        jne     doIt            # no, ready for conversion 
33        incq    %rdi            # skip plus sign 
34doIt: 
35        call    dec2uInt        # arguments are correct 
36                                # absolute value now stored 
37        cmpl    $0, negFlag(%rbp)   # negative? 
38        je      done            # no, all done 
39        negl    (%rsi)          # change sign 
40done: 
41        movl    $0, %eax        # return 0 
42        movq    %rbp, %rsp      # delete local vars 
43        popq    %rbp            # restore caller frame ptr 
44        ret
 
1# sInt2dec.s 
2# Converts signed int to corresponding signed decimal string 
3# Bob Plantz - 13 June 2009 
4 
5# Calling sequence 
6#       esi <- value of the int 
7#       rdi <- address of string 
8#       call sInt2dec 
9#       returns zero 
10# Code 
11        .section  .rodata 
12ten:  .long  10 
13 
14        .text 
15        .globlsInt2dec 
16        .type   sInt2dec, @function 
17sInt2dec: 
18        pushq  %rbp        # save callers frame ptr 
19        movq  %rsp, %rbp    # our stack frame 
20 
21        cmpl  $0, %esi        # >= 0? 
22        jge    positive      # yes, just convert it 
23        movb  $-, (%rdi)  # store minus sign 
24        incq  %rdi            # and move the pointer 
25        negl  %esi            # negate the number 
26positive: 
27        call  uInt2dec      # arguments are correct 
28 
29        movl  $0, %eax      # return 0 
30        movq  %rbp, %rsp    # delete local vars. 
31        popq  %rbp        # restore caller frame ptr 
32        ret

See above for uInt2dec and dec2uInt. See Section E.11 for writeStr and readLn.

E.13 Data Structures

13 -1

 
1# arrayIndex.s 
2# Allocates an int array and stores element number in each element. 
3# Bob Plantz - 29 June 2009 
4 
5# number of elements in the array 
6nInts = 25 
7# Stack frame 
8        .equ    rbxSave,intArray-8 
9        .equ    intArray,-4*nInts 
10        .equ    index,intArray-8  # 8 bytes to be consistent 
11                                  # with indexed addressing 
12        .equ    localSize,index 
13# Read only data 
14        .section  .rodata 
15msg: 
16        .string "The array contains:\n" 
17endl: 
18        .string "\n" 
19# Code 
20        .text 
21        .globl  main 
22        .type   main, @function 
23main: 
24        pushq   %rbp             # save caller frame pointer 
25        movq    %rsp, %rbp       # set our frame pointer 
26        addq    $localSize, %rsp # local variables 
27        andq    $-16, %rsp       # 16-byte alignment 
28        movq    %rbx, rbxSave(%rbp) # save reg for OS 
29 
30        movq    $0, index(%rbp)  # index = 0 
31        leaq    intArray(%rbp), %rbx # the array 
32 
33# store values in the array 
34storeLup: 
35        movq    index(%rbp), %rax    # get index value 
36        cmpq    $nInts, %rax     # all filled? 
37        jae     display          # yes, display it 
38 
39        movl    %eax, (%rbx,%rax,4)  # no, store index 
40 
41        incq    index(%rbp)      # index++ 
42        jmp     storeLup         # do rest of elements 
43 
44display: 
45        movq    $0, index(%rbp)  # restart at beginning 
46displayLup: 
47        movq    index(%rbp), %rax   # get index value 
48        cmpq    $nInts, %rax     # any more? 
49        jae     done             # no, all done 
50 
51        movl    (%rbx,%rax,4), %edi # yes, display it 
52        call    putInt 
53 
54        movl    $endl, %edi      # do it in a column 
55        call    writeStr 
56 
57        incq    index(%rbp)      # index++ 
58        jmp     displayLup       # do rest of elements 
59 
60done: 
61        movl    $0,  %eax        # return 0; 
62        movq    rbxSave(%rbp), %rbx  # restore reg 
63        movq    %rbp, %rsp       # remove local vars 
64        popq    %rbp             # restore caller frame ptr 
65        ret                      # back to OS
 
1# putInt.s 
2# writes a signed int to standard out 
3# Bob Plantz - 28 June 2009 
4 
5# Calling sequence 
6#       edi <- value of the int 
7#       call putInt 
8 
9# Stack frame 
10        .equ    buffer,-12 
11        .equ    localSize,-16 
12# Code 
13        .text 
14        .globl  putInt 
15        .type   putInt, @function 
16putInt: 
17        pushq   %rbp             # save callers frame ptr 
18        movq    %rsp, %rbp       # our stack frame 
19        addq    $localSize, %rsp # local vars. 
20 
21        movl    %edi, %esi       # number to convert 
22        leaq    buffer(%rbp), %rdi  # place to store string 
23        call    sInt2dec         # do the conversion to string 
24 
25        leaq    buffer(%rbp), %rdi  # place where string stored 
26        call    writeStr         # write it 
27 
28        movl    $0, %eax         # return 0 
29        movq    %rbp, %rsp       # delete local vars. 
30        popq    %rbp             # restore caller frame ptr 
31        ret

See Section E.12 fot sInt2dec. See Section E.11 for writeStr.

13 -2

 
1# sumInts.s 
2# Prompts user for 10 integers, stores them in an array, then 
3# displays their sum. 
4# Bob Plantz - 28 June 2009 
5 
6# number of elements in the array 
7        .equ    nInts,10 
8# Stack frame 
9        .equ    rbxSave,total-8 
10        .equ    total,index-4 
11        .equ    index,intArray-8 
12        .equ    intArray,-4*nInts 
13        .equ    localSize,rbxSave 
14# Read only data 
15        .section  .rodata 
16prompt: 
17        .string "Enter an integer: " 
18msg: 
19        .string "The sum is: " 
20endl: 
21        .string "\n" 
22# Code 
23        .text 
24        .globl  main 
25        .type   main, @function 
26main: 
27        pushq   %rbp             # save caller frame pointer 
28        movq    %rsp, %rbp       # set our frame pointer 
29        addq    $localSize, %rsp # local variables 
30        andq    $-16, %rsp       # 16-byte boundary 
31        movq    %rbx, rbxSave(%rbp) # save reg for OS 
32 
33        movq    $0, index(%rbp)  # index = 0 
34        leaq    intArray(%rbp), %rbx  # the array 
35 
36# store user values in the array 
37storeLup: 
38        cmpq    $nInts, index(%rbp)    # all filled? 
39        jae     sum              # yes, sum them 
40 
41        movl    $prompt, %edi    # no, prompt user 
42        call    writeStr 
43 
44        movq    index(%rbp), %rax   # get index value 
45        leaq    (%rbx,%rax,4), %rdi # place to store int 
46        call    getInt 
47 
48        incq    index(%rbp)     # index++ 
49        jmp     storeLup        # do rest of elements 
50 
51sum: 
52        movq    $0, index(%rbp) # restart at beginning 
53        movl    $0, total(%rbp) # init total 
54sumLup: 
55        cmpl    $nInts, index(%rbp)  # all summed? 
56        jae     display         # yes, display total 
57 
58        movq    index(%rbp), %rax   # get index value 
59        movl    (%rbx,%rax,4), %eax # no, add current 
60        addl    %eax, total(%rbp) 
61 
62        incq    index(%rbp)     # index++ 
63        jmp     sumLup          # do rest of elements 
64 
65display: 
66        movl    $msg, %edi      # tell user about it 
67        call    writeStr 
68 
69        movl    total(%rbp), %edi # and show the sum 
70        call    putInt 
71 
72        movl    $endl, %edi 
73        call    writeStr 
74 
75        movq    rbxSave(%rbp), %rbx  # restore reg 
76        movl    $0,  %eax       # return 0; 
77        movq    %rbp, %rsp      # remove local vars 
78        popq    %rbp            # restore caller frame ptr 
79        ret                     # back to OS
 
1# getInt.s 
2# reads an int from standard in 
3# Bob Plantz - 28 June 2009 
4 
5# Calling sequence 
6#       rdi <- pointer where to store the int 
7#       call getInt 
8#       returns 0 
9 
10# Stack frame 
11        .equ    outPtr,-24 
12        .equ    buffer,-12 
13        .equ    localSize,-32 
14# Code 
15        .text 
16        .globl  getInt 
17        .type   getInt, @function 
18getInt: 
19        pushq   %rbp             # save callers frame ptr 
20        movq    %rsp, %rbp       # our stack frame 
21        addq    $localSize, %rsp # local vars. 
22 
23        movq    %rdi, outPtr(%rbp) # save argument 
24 
25        movl    $12, %esi        # max number of chars 
26        leaq    buffer(%rbp), %rdi  # place where string stored 
27        call    readLn           # read it 
28 
29        movq    outPtr(%rbp), %rsi  # place to store number 
30        leaq    buffer(%rbp), %rdi  # address of string 
31        call    dec2sInt        # convert string to int 
32 
33        movl    $0, %eax         # return 0 
34        movq    %rbp, %rsp       # delete local vars. 
35        popq    %rbp             # restore caller frame ptr 
36        ret

See above for putInt. See Section E.12 for dec2sInt See Section E.11 for writeStr and readLn.

13 -3

 
1# averageInts 
2# Prompts user for 10 integers, stores them in an array, then 
3# displays their average. 
4# Bob Plantz - 29 June 2009 
5 
6# number of elements in the array 
7        .equ    nInts,10 
8# Stack frame 
9        .equ    rbxSave,total-8 
10        .equ    total,index-4 
11        .equ    index,intArray-8 
12        .equ    intArray,-4*nInts 
13        .equ    localSize,rbxSave 
14# Read only data 
15        .section  .rodata 
16prompt: 
17        .string "Enter an integer: " 
18msg: 
19        .string "The sum is: " 
20endl: 
21        .string "\n" 
22# Code 
23        .text 
24        .globl  main 
25        .type   main, @function 
26main: 
27        pushq   %rbp             # save caller frame pointer 
28        movq    %rsp, %rbp       # set our frame pointer 
29        addq    $localSize, %rsp # local variables 
30        andq    $-16, %rsp       # 16-byte boundary 
31        movq    %rbx, rbxSave(%rbp) # save reg for OS 
32 
33        movq    $0, index(%rbp)  # index = 0 
34        leaq    intArray(%rbp), %rbx  # the array 
35 
36# store user values in the array 
37storeLup: 
38        cmpq    $nInts, index(%rbp)    # all filled? 
39        jae     sum              # yes, sum them 
40 
41        movl    $prompt, %edi    # no, prompt user 
42        call    writeStr 
43 
44        movq    index(%rbp), %rax   # get index value 
45        leaq    (%rbx,%rax,4), %rdi # place to store int 
46        call    getInt 
47 
48        incq    index(%rbp)     # index++ 
49        jmp     storeLup        # do rest of elements 
50 
51sum: 
52        movq    $0, index(%rbp) # restart at beginning 
53        movl    $0, total(%rbp) # init total 
54sumLup: 
55        cmpl    $nInts, index(%rbp)  # all summed? 
56        jae     display         # yes, display total 
57 
58        movq    index(%rbp), %rax   # get index value 
59        movl    (%rbx,%rax,4), %eax # no, add current 
60        addl    %eax, total(%rbp) 
61 
62        incq    index(%rbp)     # index++ 
63        jmp     sumLup          # do rest of elements 
64 
65display: 
66        movl    $msg, %edi      # tell user about it 
67        call    writeStr 
68 
69 
70        movl    total(%rbp), %eax   # compute the average 
71        movl    $0, %edx        # create 64-bit dividend 
72        cmpl    $0, %eax        # is it negative? 
73        jge     pos             # no 
74        movl    $-1, %edx       # sign extend dividend 
75pos: 
76        movl    $nInts, %ebx    # get divisor 
77        idivl   %ebx            # signed division 
78 
79        movl    %eax, %edi      # and show the average 
80        call    putInt 
81 
82        movl    $endl, %edi 
83        call    writeStr 
84 
85        movq    rbxSave(%rbp), %rbx  # restore reg 
86        movl    $0,  %eax       # return 0; 
87        movq    %rbp, %rsp      # remove local vars 
88        popq    %rbp            # restore caller frame ptr 
89        ret                     # back to OS

See above for putInt and getInt. See Section E.11 for writeStr and readLn.

13 -8

 
1# structFields.s 
2# Stores user input values in three structs and echoes them 
3# Bob Plantz - 28 June 2009 
4 
5        .include "structDef.h" 
6# Stack frame 
7        .equ    buffer,z-12 
8        .equ    z,y-structSize 
9        .equ    y,x-structSize 
10        .equ    x,-structSize 
11        .equ    localSize,buffer 
12# Read only data 
13         .section  .rodata 
14userPrompt: 
15         .string "Enter data for the three structs.\n" 
16echoMsg: 
17         .string "You entered:\n" 
18endl: 
19         .string "\n" 
20# Code 
21        .text 
22        .globl  main 
23        .type   main, @function 
24main: 
25        pushq   %rbp              # save frame pointer 
26        movq    %rsp, %rbp        # our frame pointer 
27        addq    $localSize, %rsp  # local variables 
28        andq    $-16, %rsp        # stack alignment 
29 
30        movl    $userPrompt, %edi # tell user what to do 
31        call    writeStr 
32 
33        leaq    x(%rbp), %rdi     # the x struct 
34        call    getData           # get values from user 
35 
36        leaq    y(%rbp), %rdi     # the y struct 
37        call    getData           # get values from user 
38 
39        leaq    z(%rbp), %rdi     # the z struct 
40        call    getData           # get values from user 
41 
42# give the user a message 
43        movl    $echoMsg, %edi    # start display 
44        call    writeStr 
45 
46        leaq    x(%rbp), %rdi     # the x struct 
47        call    putData           # show values to user 
48 
49        leaq    y(%rbp), %rdi     # the y struct 
50        call    putData           # show values to user 
51 
52        leaq    z(%rbp), %rdi     # the z struct 
53        call    putData           # show values to user 
54 
55        movl    $endl, %edi       # do a newline 
56        call    writeStr 
57 
58        movl    $0, %eax        # return 0; 
59        movq    %rbp, %rsp      # remove local vars 
60        popq    %rbp            # restore callers frame ptr 
61        ret                     # back to OS
 
1# structDef.h 
2# Defines the struct field offsets. 
3# Bob Plantz - 28 June 2009 
4 
5# struct definition 
6        .equ    aChar,0 
7        .equ    anInt,4 
8        .equ    structSize,8
 
1# getData.s 
2# Gets user input values and stores them in a struct. 
3# Bob Plantz - 28 June 2009 
4# Calling sequence: 
5#        rdi <- address of struct 
6#        call putData 
7 
8        .include "structDef.h" 
9# Useful constant 
10        .equ    STDOUT,1 
11# Stack frame 
12        .equ    structPtr,-32 
13        .equ    buffer,-2 
14        .equ    localSize,-32 
15# Read only data 
16        .section  .rodata 
17charPrompt: 
18         .string "Enter a single character: " 
19intPrompt: 
20         .string "Enter an integer: " 
21# Code 
22        .text 
23        .globl  getData 
24        .type   getData, @function 
25getData: 
26        pushq   %rbp               # save frame pointer 
27        movq    %rsp, %rbp         # our frame pointer 
28        addq    $localSize, %rsp   # local var. and arg. 
29        movq    %rdi, structPtr(%rbp) # save argument 
30 
31        movl    $charPrompt, %edi  # prompt user for character 
32        call    writeStr 
33 
34        movl    $2, %esi           # local buffer size 
35        leaq    buffer(%rbp), %rdi # place to store input 
36        call    readLn             # get user response 
37 
38        movb    buffer(%rbp), %al  # first char entered 
39        movq    structPtr(%rbp), %rdi 
40        movb    %al, aChar(%rdi)   # x.aChar = buffer[0] 
41 
42        movl    $intPrompt, %edi   # prompt user for integer 
43        call    writeStr 
44        movq    structPtr(%rbp), %rdi 
45        leaq    anInt(%rdi), %rdi  # place for the int 
46        call    getInt             # get user response 
47 
48        movl    $0, %eax        # return 0; 
49        movq    %rbp, %rsp      # remove local vars 
50        popq    %rbp            # restore callers frame ptr 
51        ret                     # back to caller
 
1# putData.s 
2# Displays values stored in a struct. 
3# Bob Plantz - 28 June 2009 
4# Calling sequence: 
5#        rdi <- address of struct 
6#        call putData 
7 
8        .include "structDef.h" 
9# Useful constant 
10        .equ    STDOUT,1 
11# Stack frame 
12        .equ    structPtr,-16 
13        .equ    localSize,-16 
14# Read only data 
15        .section  .rodata 
16charMsg: 
17        .string "The char is: " 
18intMsg: 
19        .string "The int is: " 
20endl: 
21        .string "\n" 
22# Code 
23        .text 
24        .globl  putData 
25        .type   putData, @function 
26putData: 
27        pushq   %rbp             # save frame pointer 
28        movq    %rsp, %rbp       # our frame pointer 
29        addq    $localSize, %rsp # argument save area 
30        movq    %rdi, structPtr(%rbp)  # save struct addr. 
31 
32 
33        movq    $charMsg, %rdi   # tell user about character 
34        call    writeStr 
35        movq    structPtr(%rbp), %rsi  # the struct 
36        movl    $1, %edx         # one byte 
37        leaq    aChar(%rsi), %rsi      # address of the char 
38        movl    $STDOUT, %edi 
39        call    write 
40        movl    $endl, %edi      # some nice formatting 
41        call    writeStr 
42 
43        movl    $intMsg, %edi    # tell user about integer 
44        call    writeStr 
45        movq    structPtr(%rbp), %rdi  # the struct 
46        movl    anInt(%rdi), %edi 
47        call    putInt           # display the integer 
48        movl    $endl, %edi      # some nice formatting 
49        call    writeStr 
50 
51        movl    $0, %eax        # return 0; 
52        movq    %rbp, %rsp      # remove local vars 
53        popq    %rbp            # restore callers frame ptr 
54        ret                     # back to OS

See above for putInt and getInt. See Section E.11 for writeStr and readLn.

13 -9

 
1# totalCost.s 
2# Gets names and prices for three items and shows total cost 
3# Bob Plantz - 29 June 2009 
4 
5        .include "item.h" 
6# Stack frame 
7        .equ    third,second-itemSize 
8        .equ    second,first-itemSize 
9        .equ    first,-itemSize 
10        .equ    localSize,third 
11# Read only data 
12        .section  .rodata 
13endl:   .string "\n" 
14totalMsg: 
15        .string "Their total cost is $" 
16# Code 
17        .text 
18        .globl  main 
19        .type   main, @function 
20main: 
21        pushq   %rbp             # save frame pointer 
22        movq    %rsp, %rbp       # our frame pointer 
23        addq    $localSize, %rsp # local variables 
24        andq    $-16, %rsp       # 16-byte boundary 
25 
26# get values into each of the struct variables 
27        leaq    first(%rbp), %rdi  # address of first struct 
28        call    getItem            # gets the values 
29        leaq    second(%rbp), %rdi # address of second struct 
30        call    getItem 
31        leaq    third(%rbp), %rdi  # address of third struct 
32        call    getItem 
33 
34# display them 
35        leaq    first(%rbp), %rdi  # address of first struct 
36        call    displayItem        # displays the values 
37        leaq    second(%rbp), %rdi # address of second struct 
38        call    displayItem 
39        leaq    third(%rbp), %rdi  # address of third struct 
40        call    displayItem 
41 
42# Now show their total cost 
43        movl    $totalMsg, %edi    # message for user 
44        call    writeStr 
45 
46        leaq    first(%rbp), %rsi  # first item 
47        movl    cost(%rsi), %edi   # accumulate sum in eax 
48        leaq    second(%rbp), %rsi # second item 
49        addl    cost(%rsi), %edi   # add to sum 
50        leaq    third(%rbp), %rsi  # third item 
51        addl    cost(%rsi), %edi   # add to sum 
52        call    putInt             # argument in correct reg. 
53 
54        movl    $endl, %edi        #  do a newline for user 
55        call    writeStr 
56 
57        movl    $0, %eax        # return 0; 
58        movq    %rbp, %rsp      # remove local vars 
59        popq    %rbp            # restore callers frame ptr 
60        ret                     # back to OS
 
1# item.h 
2# Fields and size of an item struct 
3# Bob Plantz - 29 June 2009 
4 
5        .equ    name,0 
6        .equ    cost,52 
7        .equ    itemSize,56
 
1# displayItem.s 
2# displays an item 
3# Bob Plantz - 29 June 2009 
4 
5# Calling sequence 
6#       rdi <- address of item struct 
7#       call getItem 
8#       returns void 
9 
10        .include "item.h" 
11# Stack frame 
12        .equ    structPtr,-16 
13        .equ    localSize,-16 
14# Read only data 
15        .section  .rodata 
16costMsg: 
17        .string "Cost: $" 
18nameMsg: 
19        .string "Name: " 
20endl: 
21        .string "\n" 
22spacing: 
23        .string "     " 
24# Code 
25        .text 
26        .globl  displayItem 
27        .type   displayItem, @function 
28displayItem: 
29        pushq   %rbp             # save callers frame ptr 
30        movq    %rsp, %rbp       # our stack frame 
31        addq    $localSize, %rsp # local vars 
32        movq    %rdi, structPtr(%rbp) # save arg. 
33 
34        movl    $nameMsg, %edi   # name message 
35        call    writeStr 
36        movq    structPtr(%rbp), %rdi # struct address 
37        leaq    name(%rdi), %rdi # get pointer to name 
38        call    writeStr         # show name 
39 
40        movl    $spacing, %edi   # do some formatting 
41        call    writeStr 
42 
43        movl    $costMsg, %edi   # cost message 
44        call    writeStr 
45        movq    structPtr(%rbp), %rdi # struct address 
46        movl    cost(%rdi), %edi # the integer 
47        call    putInt           # write it 
48 
49        movl    $endl, %edi      # newline 
50        call    writeStr 
51 
52        movq    %rbp, %rsp       # delete local vars. 
53        popq    %rbp             # restore callers frame ptr 
54        ret
 
1# getItem.s 
2# prompts user to enter an item name and its cost 
3# Bob Plantz - 29 June 2009 
4 
5# Calling sequence 
6#       rdi <- address of item struct 
7#       call getItem 
8#       returns void 
9 
10        .include "item.h" 
11# Stack frame 
12        .equ    structPtr,-16 
13        .equ    localSize,-16 
14# Read only data 
15        .section  .rodata 
16costMsg: 
17        .string "Enter cost: $" 
18nameMsg: 
19        .string "Name: " 
20# Code 
21        .text 
22        .globl  getItem 
23        .type   getItem, @function 
24getItem: 
25        pushq   %rbp             # save callers frame ptr 
26        movq    %rsp, %rbp       # our stack frame 
27        addq    $localSize, %rsp # local vars. 
28        movq    %rdi, structPtr(%rbp) # save arg. 
29 
30        movl    $nameMsg, %edi   # prompt for name 
31        call    writeStr 
32        movq    structPtr(%rbp), %rdi  # struct address 
33        leaq    name(%rdi), %rdi # pointer to name field 
34        movl    $50, %esi        # max name length 
35        call    readLn           # get name 
36 
37        movl    $costMsg, %edi   # prompt for cost 
38        call    writeStr 
39        movq    structPtr(%rbp), %rdi  # struct address 
40        leaq    cost(%rdi), %rdi # pointer to cost field 
41        call    getInt           # get user input 
42 
43        movq    %rbp, %rsp       # delete local vars. 
44        popq    %rbp             # restore callers frame ptr 
45        ret

See above for putInt and getInt. See Section E.11 for writeStr and readLn.

13 -10

 
1# addInt2Frac.s 
2# creates a fraction and gets user values, then gets an 
3# integer from user and adds it to the fraction. 
4# Bob Plantz - 29 June 2009 
5 
6        .include "fraction.h" 
7 
8# Stack frame 
9        .equ    anInt,x-4 
10        .equ    x,-fracSize 
11        .equ    localSize,anInt 
12 
13# Read only data 
14        .section  .rodata 
15prompt: 
16        .string "Enter an integer: " 
17endl: 
18        .string "\n" 
19# Code 
20        .text 
21        .globl  main 
22        .type   main, @function 
23main: 
24        pushq   %rbp            # save frame pointer 
25        movq    %rsp, %rbp      # our frame pointer 
26        addq    $localSize, %rsp # local variables 
27        andq    $-16, %rsp      # align stack pointer 
28 
29        leaq    x(%rbp), %rdi   # load address of object 
30        call    fraction        # call "constructor" 
31 
32        leaq    x(%rbp), %rdi   # load address of object 
33        call    fractionGet     # get "member function" 
34 
35        movl    $prompt, %edi   # ask user for a number 
36        call    writeStr 
37        leaq    anInt(%rbp), %rdi # and get it 
38        call    getInt 
39 
40        movl    anInt(%rbp), %esi # value to add to fraction 
41        leaq    x(%rbp), %rdi   # load address of object 
42        call    fractionAdd     # add "member function" 
43 
44        leaq    x(%rbp), %rdi   # load address of object 
45        call    fractionDisplay # display "member function" 
46 
47        movl    $endl, %edi     # formatting 
48        call    writeStr 
49 
50        movl    $0, %eax        # return 0; 
51        movq    %rbp, %rsp      # delete local vars. 
52        popq    %rbp            # restore base pointer for OS 
53        ret                     # back to caller (OS)

See above for getInt. See Section E.11 for writeStr.

13 -11

 
1# addFrac2Frac.s 
2# creates two fractions and gets user values, then adds 
3# one to the other and displays the sum. 
4# Bob Plantz - 30 June 2009 
5 
6        .include "fraction.h" 
7 
8# Stack frame 
9        .equ    y,x-fracSize 
10        .equ    x,-fracSize 
11        .equ    localSize,y 
12# Read only data 
13        .section .rodata 
14prompt: 
15        .string "Enter two fractions:\n" 
16msg: 
17        .string "Their sum is:\n" 
18endl: 
19        .string "\n" 
20# Code 
21        .text 
22        .globl  main 
23        .type   main, @function 
24main: 
25        pushq   %rbp             # save frame pointer 
26        movq    %rsp, %rbp       # our frame pointer 
27        addq    $localSize, %rsp # local vars. 
28        andq    $-16, %rsp       # align stack pointer 
29 
30        leaq    x(%rbp), %rdi    # pass address of object 
31        call    fraction         #   to "constructor" 
32        leaq    y(%rbp), %rdi    # pass address of object 
33        call    fraction         #   to "constructor" 
34 
35        movl    $prompt, %edi    # tell user what to do 
36        call    writeStr 
37 
38        leaq    x(%rbp), %rdi    # get address of object 
39        call    fractionGet     # get "member function" 
40        leaq    y(%rbp), %rdi    # get address of object 
41        call    fractionGet      # get "member function" 
42 
43        leaq    y(%rbp), %rsi    # address of argument 
44        leaq    x(%rbp), %rdi    # address of object 
45        call    fractionsAdd     # add "member function" 
46 
47        movl    $msg, %edi       # tell user what happened 
48        call    writeStr 
49        leaq    x(%rbp), %rdi    # get address of object 
50        call    fractionDisplay # display "member function" 
51        movl    $endl, %edi     # formatting 
52        call    writeStr 
53 
54        movq    %rbp, %rsp      # delete local vars. 
55        popq    %rbp            # restore frane pointer 
56        ret                     # back to caller
 
1# fractionsAdd.s 
2# adds a fraction to this fraction 
3# Bob Plantz - 30 June 2009 
4 
5# Calling sequence 
6#       rsi <- address of object to add 
7#       rdi <- address of this object 
8#       call   fractionsAdd 
9#       returns void 
10 
11        .include "fraction.h" 
12# Stack frame 
13        .equ    localFraction,-fracSize 
14        .equ    localSize,localFraction 
15# Code 
16        .text 
17        .globl  fractionsAdd 
18        .type   fractionAdd, @function 
19fractionsAdd: 
20        pushq   %rbp             # save frame pointer 
21        movq    %rsp, %rbp       # our frame pointer 
22        addq    $localSize, %rsp # for object address 
23        andq    $-16, %rsp       # align stack pointer 
24        leaq    localFraction(%rbp), %rcx  # pointer to local fraction 
25 
26        movl    den(%rsi), %eax  # multiply the denominators 
27        mull    den(%rdi) 
28        movl    %eax, den(%rcx)  # new denominator 
29 
30        movl    num(%rdi), %eax # get this numerator 
31        mull    den(%rsi)       # multiply by arg denominator 
32        movl    %eax, num(%rcx) # and store in local num 
33 
34        movl    num(%rsi), %eax # get arg num 
35        mull    den(%rdi)       # multiply by this den 
36        addl    %eax, num(%rcx) # and add to local num 
37 
38        movl    num(%rcx), %eax # copy back to this object 
39        movl    %eax, num(%rdi) 
40        movl    den(%rcx), %eax 
41        movl    %eax, den(%rdi) 
42 
43        movq    %rbp, %rsp      # delete local vars. 
44        popq    %rbp            # restore frane pointer 
45        ret                     # back to caller

See Section E.11 for writeStr.

13 -12

 
1# addressBook.s 
2# Allows up to MAX address cards to be stored. 
3# Bob Plantz - 30 June 2009 
4 
5        .include "cardDef.h" 
6# Set MAX for the maximum number of cards 
7        .equ    MAX,3 
8# Stack frame 
9        .equ    count,index-4 
10        .equ    index,cards-4 
11        .equ    cards,buffer-(MAX*cardSize) 
12        .equ    buffer,-32 
13        .equ    localSize,count 
14# Read only data 
15        .section  .rodata 
16prompt: 
17        .string "Command (Add, Delete, Show, List, Quit): " 
18addMsg: 
19        .string "Add new person.\n " 
20delMsg: 
21        .string "Delete last person.\n" 
22showMsg: 
23        .string "Your addresses:\n" 
24listMsg: 
25        .string "Here is the entire array:\n" 
26fullMsg: 
27        .string "Address book is full.\n" 
28emptyMsg: 
29        .string "Address book is empty.\n" 
30endl: 
31        .string "\n" 
32# Code 
33        .text 
34        .globl  main 
35        .type   main, @function 
36main: 
37        pushq   %rbp             # save frame pointer 
38        movq    %rsp, %rbp       # our frame pointer 
39        addq    $localSize, %rsp # local variables 
40        andq    $-16, %rsp       # align stack pointer 
41 
42# construct the array objects 
43        movl    $0, index(%rbp)   # start at beginning 
44constLup: 
45        cmpl    $MAX, index(%rbp) # end of list? 
46        jae     doProg            # yes, run the program 
47        leaq    cards(%rbp), %rdi # no, beginning of list 
48        movl    $cardSize, %eax   # length of each record 
49        mull    index(%rbp)       # times current location 
50        addq    %rax, %rdi        # points to current record 
51        call    card              # call constructor 
52        incl    index(%rbp) 
53        jmp     constLup 
54 
55doProg: 
56        movl    $0, count(%rbp) # no people yet 
57runLoop: 
58        movl    $prompt, %edi   # tell user what to do 
59        call    writeStr 
60 
61        movl    $32, %esi           # max number of chars 
62        leaq    buffer(%rbp), %rdi  # place for user input 
63        call    readLn              # get user command 
64        orb     $0x20, buffer(%rbp) # make first char lower case 
65 
66        cmpb    $q, buffer(%rbp)  # quit? 
67        je      allDone 
68 
69        cmpb    $a, buffer(%rbp)  # check for add command 
70        jne     chkDel 
71        cmpl    $MAX, count(%rbp)   # check for full list 
72        jb      doAdd               # theres space 
73        movl    $fullMsg, %edi      # array is full 
74        call    writeStr 
75        jmp     cont 
76doAdd: 
77        movl    $addMsg, %edi       # feedback for user 
78        call    writeStr 
79        leaq    cards(%rbp), %rdi   # the array 
80        movl    $cardSize, %eax     # length of each record 
81        mull    count(%rbp)         # times number of records in array 
82        addq    %rax, %rdi          # points to next open space 
83        call    cardGet             # fill it in 
84        incl    count(%rbp) 
85        jmp     cont 
86 
87chkDel: 
88        cmpb    $d, buffer(%rbp)  # check for delete command 
89        jne     chkShow 
90        cmpl    $0, count(%rbp)     # anybody on the list? 
91        ja      doDel               # yes, delete last one 
92        movl    $emptyMsg, %edi     # no, tell user 
93        call    writeStr 
94        jmp     cont 
95doDel: 
96        movl    $delMsg, %edi       # feedback for user 
97        call    writeStr 
98        decl    count(%rbp) 
99        jmp     cont 
100 
101chkShow: 
102        cmpb    $s, buffer(%rbp)  # check for show command 
103        jne     chkList 
104        cmpl    $0, count(%rbp)     # anybody on the list? 
105        ja      doShow              # yes, show them 
106        movl    $emptyMsg, %edi     # no, tell user 
107        call    writeStr 
108        jmp     cont 
109doShow: 
110        movl    $showMsg, %edi      # feedback for user 
111        call    writeStr 
112 
113        movl    $0, index(%rbp)     # start at beginning 
114showLup: 
115        movl    count(%rbp), %eax 
116        cmpl    %eax, index(%rbp)   # all names? 
117        jae     cont                # yes, next thing 
118        leaq    cards(%rbp), %rdi   # the array 
119        movl    $cardSize, %eax     # length of each record 
120        mull    index(%rbp)         # times number of records in array 
121        addq    %rax, %rdi          # points to current card 
122        call    cardPut 
123        incl    index(%rbp) 
124        jmp     showLup 
125 
126chkList: 
127        cmpb    $l, buffer(%rbp)  # check for list command 
128        jne     cont 
129        movl    $listMsg, %edi      # feedback for user 
130        call    writeStr 
131 
132        movl    $0, index(%rbp)     # start at beginning 
133listLup: 
134        cmpl    $MAX, index(%rbp)   # end of list? 
135        jae     cont                # yes, next thing 
136        leaq    cards(%rbp), %rdi   # the array 
137        movl    $cardSize, %eax     # length of each record 
138        mull    index(%rbp)         # times number of records in array 
139        addq    %rax, %rdi          # points to current card 
140        call    cardPut 
141        incl    index(%rbp) 
142        jmp     listLup 
143cont: 
144        jmp     runLoop 
145allDone: 
146        movl    $0, %eax        # return 0; 
147        movq    %rbp, %rsp      # remove local vars 
148        popq    %rbp            # restore callers frame ptr 
149        ret                     # back to OS
 
1# cardDef.h 
2# Defines the address card field offsets. 
3# Bob Plantz - 30 June 2009 
4 
5# card definition 
6        .equ    name,0 
7        .equ    address,name+48 
8        .equ    city,address+80 
9        .equ    state,city+24 
10        .equ    zip,state+20 
11        .equ    cardSize,zip+6
 
1# card.s 
2# card object default constructor. 
3# Bob Plantz - 30 June 2009 
4# Calling sequence: 
5#       rdi <- address of object 
6#       call card 
7#       returns void 
8 
9        .include "cardDef.h" 
10# Stack frame 
11        .equ    thisPtr,-16 
12        .equ    localSize,-16 
13# Read only data 
14        .section  .rodata 
15nameDefault: 
16        .string "J. Doe" 
17addressDefault: 
18        .string "123 Main St." 
19cityDefault: 
20        .string "Middle Town" 
21stateDefault: 
22        .string "Kansas" 
23zipDefault: 
24        .string "12345" 
25# Code 
26        .text 
27        .globl  card 
28        .type   card, @function 
29card: 
30        pushq   %rbp             # save frame pointer 
31        movq    %rsp, %rbp       # our frame pointer 
32        addq    $localSize, %rsp # for saving argument 
33        movq    %rdi, thisPtr(%rbp)   # save it 
34 
35# Copy default data into the fields 
36        movl    $nameDefault, %edx    # name 
37        movq    thisPtr(%rbp), %rsi 
38        leaq    name(%rsi), %rsi      # place to store string 
39        movl    $(address-name), %edi # max number of chars 
40        call    copyStr 
41 
42        movl    $addressDefault, %edx # address 
43        movq    thisPtr(%rbp), %rsi 
44        leaq    address(%rsi), %rsi   # place to store string 
45        movl    $(city-address), %edi # max number of chars 
46        call    copyStr 
47 
48        movl    $cityDefault, %edx    # city 
49        movq    thisPtr(%rbp), %rsi 
50        leaq    city(%rsi), %rsi      # place to store string 
51        movl    $(state-city), %edi   # max number of chars 
52        call    copyStr 
53 
54        movl    $stateDefault, %edx   # state 
55        movq    thisPtr(%rbp), %rsi 
56        leaq    state(%rsi), %rsi     # place to store string 
57        movl    $(zip-state), %edi    # max number of chars 
58        call    copyStr 
59 
60        movl    $zipDefault, %edx     # state 
61        movq    thisPtr(%rbp), %rsi 
62        leaq    zip(%rsi), %rsi       # place to store string 
63        movl    $(cardSize-zip), %edi # max number of chars 
64        call    copyStr 
65 
66        movq    %rbp, %rsp      # remove local vars 
67        popq    %rbp            # restore callers frame ptr 
68        ret                     # back to caller
 
1# copyStr.s 
2# Copies a C-style text string. 
3# 
4# Calling sequence: 
5#       rdx <- address of source 
6#       rsi <- address of destination 
7#       edi <- maximum length to copy (including NULL) 
8#       call copyStr 
9#   returns number of chars copied, not including NULL. 
10# assumes maximum length is at least 1. 
11# Bob Plantz - 30 June 2009 
12 
13# Code 
14        .text 
15        .globl  copyStr 
16        .type   copyStr, @function 
17copyStr: 
18        pushq   %rbp             # save frame pointer 
19        movq    %rsp, %rbp       # our frame pointer 
20 
21        subl    $1, %edi         # allow room for NULL 
22        movl    $0, %eax         # count = 0 
23loop: 
24        cmpl    %eax, %edi       # any more space? 
25        jle     done             # no, have to quit 
26        movb    (%rdx), %cl      # yes, get a char 
27        cmpb    $0, %cl          # NULL? 
28        je      done             # yes, copy is done 
29        movb    %cl, (%rsi)      # no, copy the char 
30        incq    %rdx             # increment our pointers 
31        incq    %rsi 
32        incl    %eax             # and the counter 
33        jmp     loop             # and check for more 
34 
35done:   movb    $0, (%rsi)       # store NULL char 
36 
37        movq    %rbp, %rsp       # remove local vars 
38        popq    %rbp             # restore callers frame ptr 
39        ret                      # back to caller
 
1# cardGet.s 
2# Gets user input values and stores them in a card object. 
3# 
4# Calling sequence: 
5#        rdi <- address of object 
6#        call cardGet 
7# Bob Plantz - 30 June 2009 
8 
9        .include "cardDef.h" 
10# Stack frame 
11        .equ    thisPtr,-16 
12        .equ    localSize,-16 
13# Read only data 
14         .section  .rodata 
15Prompt: 
16         .string "Enter the data\n" 
17namePrompt: 
18         .string "         name: " 
19addressPrompt: 
20         .string "      address: " 
21cityPrompt: 
22         .string "         city: " 
23statePrompt: 
24         .string "        state: " 
25zipPrompt: 
26         .string "     zip code: " 
27# Code 
28        .text 
29        .globl  cardGet 
30        .type   cardGet, @function 
31cardGet: 
32        pushq   %rbp              # save frame pointer 
33        movq    %rsp, %rbp        # our frame pointer 
34        addq    $localSize, %rsp  # local vars. 
35        movq    %rdi, thisPtr(%rbp)  # address of object 
36 
37        movl    $Prompt, %edi     # tell use to enter data 
38        call    writeStr 
39# get user responses 
40        movl    $namePrompt, %edi     # name 
41        call    writeStr 
42        movl    $(address-name), %esi # space allocated for name 
43        movq    thisPtr(%rbp), %rdi   # our object 
44        leaq    name(%rdi), %rdi      # name field 
45        call    readLn 
46 
47        movl    $addressPrompt, %edi   # address 
48        call    writeStr 
49        movl    $(city-address), %esi  # space allocated for address 
50        movq    thisPtr(%rbp), %rdi    # our object 
51        leaq    address(%rdi), %rdi    # address field 
52        call    readLn 
53 
54        movl    $cityPrompt, %edi      # city 
55        call    writeStr 
56        movl    $(state-city), %esi    # space allocated for city 
57        movq    thisPtr(%rbp), %rdi    # our object 
58        leaq    city(%rdi), %rdi       # city field 
59        call    readLn 
60 
61        movl    $statePrompt, %edi     # state 
62        call    writeStr 
63        movl    $(zip-state), %esi     # space allocated for state 
64        movq    thisPtr(%rbp), %rdi    # our object 
65        leaq    state(%rdi), %rdi      # state field 
66        call    readLn 
67 
68        movl    $zipPrompt, %edi       # zip code 
69        call    writeStr 
70        movl    $(cardSize-zip), %esi  # space allocated for zip 
71        movq    thisPtr(%rbp), %rdi    # our object 
72        leaq    zip(%rdi), %rdi        # zip field 
73        call    readLn 
74 
75        movl    $0, %eax        # return 0; 
76        movq    %rbp, %rsp      # remove local vars 
77        popq    %rbp            # restore callers frame ptr 
78        ret                     # back to OS
 
1# cardPut.s 
2# Displays a card object. 
3# 
4# Calling sequence: 
5#        rdi <- address of object 
6#        call cardPut 
7# Bob Plantz - 30 June 2009 
8 
9        .include "cardDef.h" 
10# Stack frame 
11        .equ    thisPtr,-16 
12        .equ    localSize,-16 
13# Read only data 
14         .section  .rodata 
15Msg: 
16         .string "*** Address Card ***\n" 
17nameMsg: 
18         .string "      name: " 
19addressMsg: 
20         .string "   address: " 
21cityMsg: 
22         .string "      city: " 
23stateMsg: 
24         .string "     state: " 
25zipMsg: 
26         .string "  zip code: " 
27endl: 
28         .string "\n" 
29# Code 
30        .text 
31        .globl  cardPut 
32        .type   cardPut, @function 
33cardPut: 
34        pushq   %rbp              # save frame pointer 
35        movq    %rsp, %rbp        # our frame pointer 
36        addq    $localSize, %rsp  # local vars. 
37        movq    %rdi, thisPtr(%rbp)  # address of object 
38 
39        movl    $Msg, %edi        # tell user about data 
40        call    writeStr 
41 
42# show each field 
43        movl    $nameMsg, %edi    # name 
44        call    writeStr 
45        movq    thisPtr(%rbp), %rdi # our object 
46        leaq    name(%rdi), %rdi  # name field 
47        call    writeStr 
48        movl    $endl, %edi       # next line (nb: I do them 
49        call    writeStr          # individually so its easier 
50 
51        movl    $addressMsg, %edi # address 
52        call    writeStr 
53        movq    thisPtr(%rbp), %rdi # our object 
54        leaq    address(%rdi), %rdi # address field 
55        call    writeStr 
56        movl    $endl, %edi       # next line (nb: I do them 
57        call    writeStr          # individually so its easier 
58 
59        movl    $cityMsg, %edi    # city 
60        call    writeStr 
61        movq    thisPtr(%rbp), %rdi # our object 
62        leaq    city(%rdi), %rdi  # city field 
63        call    writeStr 
64        movl    $endl, %edi       # next line (nb: I do them 
65        call    writeStr          # individually so its easier 
66 
67        movl    $stateMsg, %edi   # state 
68        call    writeStr 
69        movq    thisPtr(%rbp), %rdi # our object 
70        leaq    state(%rdi), %rdi # state field 
71        call    writeStr 
72        movl    $endl, %edi       # next line (nb: I do them 
73        call    writeStr          # individually so its easier 
74 
75        movl    $zipMsg, %edi     # zip 
76        call    writeStr 
77        movq    thisPtr(%rbp), %rdi # our object 
78        leaq    zip(%rdi), %rdi # zip field 
79        call    writeStr 
80        movl    $endl, %edi       # next line (nb: I do them 
81        call    writeStr          # individually so its easier 
82 
83        movl    $0, %eax        # return 0 
84        movq    %rbp, %rsp      # remove local vars 
85        popq    %rbp            # restore callers frame ptr 
86        ret                     # back to OS

See Section E.11 for writeStr and readLn.

E.14 Fractional Numbers

14 -1

 
1/* 
2 * floatLoop.c 
3 * shows how round off error breaks a loop control variable 
4 * Bob Plantz - 1 July 2009 
5 */ 
6 
7#include <stdio.h> 
8 
9int main() 
10{ 
11    float number; 
12    int counter = 10; 
13 
14    number = 0.5; 
15    while ((number != 0.0) && (counter != 0)) 
16    { 
17        printf("number = %f and counter = %i\n", number, counter); 
18 
19        number -= 0.1;   // change to 0.0625 to fix 
20        counter -= 1; 
21    } 
22 
23    return 0; 
24}
14 -2

 
1/* 
2 * floatRoundoff.c 
3 * shows the effects of adding a small float to a large one. 
4 * Bob Plantz - 1 July 2009 
5 */ 
6 
7#include <stdio.h> 
8 
9int main() 
10{ 
11    float fNumber = 2147483646.0; 
12    int iNumber = 2147483646; 
13 
14    printf("Before adding the float is %f and the integer is %i\n", 
15         fNumber, iNumber); 
16    fNumber += 1.0; 
17    iNumber += 1; 
18    printf("After adding 1 the float is %f and the integer is %i\n", 
19         fNumber, iNumber); 
20 
21    return 0; 
22}
14 -5

The following program is provided for you to work with these conversions.

 
1/* 
2 * float2hex.c 
3 * allows user to see bit pattern of a float 
4 * Bob Plantz - 1 July 2009 
5 */ 
6 
7#include <stdio.h> 
8 
9int main() 
10{ 
11    float number; 
12    unsigned int *ptr = (unsigned int *)&number; 
13    char ans[50]; 
14 
15    *ans = y; 
16    while ((*ans == y) || (*ans == Y)) 
17    { 
18        printf("Enter a decimal number: "); 
19        scanf("%f", &number); 
20        printf("%f => %#0x\n", number, *ptr); 
21 
22        printf("Continue (y/n)? "); 
23        scanf("%s", ans); 
24    } 
25 
26    return 0; 
27}

a) 3f800000 b) bdcccccd c) 44faa000 d) 3b800000 e) c5435500 f) 3ea8f5c3 g) 4048f5c3

14 -6

The following program is provided for you to work with these conversion.

 
1/* 
2 * hex2float.c 
3 * converts hex pattern to float 
4 * Bob Plantz - 1 July 2009 
5 */ 
6 
7#include <stdio.h> 
8 
9int main() 
10{ 
11    unsigned int number; 
12    float *ptr = (float *)&number; 
13    char ans[50]; 
14 
15    *ans = y; 
16    while ((*ans == y) || (*ans == Y)) 
17    { 
18        printf("Enter a hex number: "); 
19        scanf("%x", &number); 
20        printf("%#0x => %f\n", number, *ptr); 
21 
22        printf("Continue (y/n)? "); 
23        scanf("%s", ans); 
24    } 
25 
26    return 0; 
27}

a) +2.0 b) -1.0 c) +0.0625 d) -16.03125 e) 100.03125 f) 1.2 g) 123.449997 h) -54.320999

14 -7

The bit pattern for +2.0 is 01000...0. Because IEEE 754 uses a biased exponent format, all the floating point numbers in the range 0.0 – +2.0 are within the bit pattern range 00000...0 01000...0. So half the positive floating point numbers are in the range 00000...0 00111...0, and the other half in the range 01000...0 01111...1.

The same argument applies to the negative floating point numbers.

14 -8

 
1        .file  "casting.c" 
2        .section      .rodata 
3.LC0: 
4        .string"Enter an integer: " 
5.LC1: 
6        .string"%i" 
7.LC3: 
8        .string"%i + %lf = %lf\n" 
9        .text 
10        .globlmain 
11        .type  main, @function 
12main: 
13        pushq  %rbp 
14        movq  %rsp, %rbp 
15        subq  $48, %rsp 
16        movl  $.LC0, %edi 
17        movl  $0, %eax 
18        call  printf 
19        leaq  -20(%rbp), %rax 
20        movq  %rax, %rsi 
21        movl  $.LC1, %edi 
22        movl  $0, %eax 
23        call  __isoc99_scanf 
24        movabsq$4608218246714312622, %rax # y = 1.23; 
25        movq  %rax, -16(%rbp)            # store y 
26        movl  -20(%rbp), %eax            # load x 
27        cvtsi2sd      %eax, %xmm0        # xmm0 = (double)x 
28        addsd  -16(%rbp), %xmm0           # xmm0 += y 
29        movsd  %xmm0, -8(%rbp)            # z = xmm0 
30        movl  -20(%rbp), %ecx 
31        movq  -8(%rbp), %rdx 
32        movq  -16(%rbp), %rax 
33        movq  %rdx, -40(%rbp) 
34        movsd  -40(%rbp), %xmm1 
35        movq  %rax, -40(%rbp) 
36        movsd  -40(%rbp), %xmm0 
37        movl  %ecx, %esi 
38        movl  $.LC3, %edi 
39        movl  $2, %eax 
40        call  printf 
41        movl  $0, %eax 
42        leave 
43        ret 
44        .size  main, .-main 
45        .ident"GCC: (Ubuntu/Linaro 4.7.0-7ubuntu3) 4.7.0" 
46        .section      .note.GNU-stack,"",@progbits

E.15 Interrupts and Exceptions

15 -1

 
1# myCatC.s 
2# Writes a file to standard out 
3# Runs in C environment, but does not use C libraries. 
4# Bob Plantz - 1 July 2009 
5 
6# Useful constants 
7        .equ    STDIN,0 
8        .equ    STDOUT,1 
9        .equ    theArg,8 
10   # from asm/unistd_64.h 
11        .equ    READ,0 
12        .equ    WRITE,1 
13        .equ    OPEN,2 
14        .equ    CLOSE,3 
15        .equ    EXIT,60 
16   # from bits/fcntl.h 
17        .equ    O_RDONLY,0 
18        .equ    O_WRONLY,1 
19        .equ    O_RDWR,3 
20# Stack frame 
21        .equ    aLetter,-16 
22        .equ    fd, -8 
23        .equ    localSize,-16 
24# Code 
25        .text                  # switch to text segment 
26        .globl  main 
27        .type   main, @function 
28main: 
29        pushq   %rbp           # save callers frame pointer 
30        movq    %rsp, %rbp     # establish our frame pointer 
31        addq    $localSize, %rsp   # for local variable 
32 
33        movl    $OPEN, %eax        # open the file 
34        movq    theArg(%rsi), %rdi # the filename 
35        movl    $O_RDONLY, %esi    # read only 
36        syscall 
37        movl    %eax, fd(%rbp)     # save file descriptor 
38 
39        movl    $READ, %eax 
40        movl    $1, %edx           # 1 character 
41        leaq    aLetter(%rbp), %rsi # place to store character 
42        movl    fd(%rbp), %edi     # standard in 
43        syscall                    # request kernel service 
44 
45writeLoop: 
46        cmpl    $0, %eax           # any chars? 
47        je      allDone            # no, must be end of file 
48        movl    $1, %edx           # yes, 1 character 
49        leaq    aLetter(%rbp), %rsi # place to store character 
50        movl    $STDOUT, %edi      # standard out 
51        movl    $WRITE, %eax 
52        syscall                    # request kernel service 
53 
54        movl    $READ, %eax        # read next char 
55        movl    $1, %edx           # 1 character 
56        leaq    aLetter(%rbp), %rsi # place to store character 
57        movl    fd(%rbp), %edi     # standard in 
58        syscall                    # request kernel service 
59        jmp     writeLoop          # check the char 
60allDone: 
61        movl    $CLOSE, %eax       # close the file 
62        movl    fd(%rbp), %edi     # file descriptor 
63        syscall                    # request kernel service 
64        movq    %rbp, %rsp         # delete local variables 
65 
66        popq    %rbp               # restore callers frame pointer 
67        movl    $EXIT, %eax        # end this process 
68        syscall