Difference between revisions of "CSC231 Homework 5 2010"

From dftwiki3
Jump to: navigation, search
 
(10 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
--[[User:Thiebaut|D. Thiebaut]] 19:54, 20 October 2010 (UTC)
 +
----
 +
 
<meta name="keywords" content="computer science, assembly language, pentium, exercise, machine language, intel" />
 
<meta name="keywords" content="computer science, assembly language, pentium, exercise, machine language, intel" />
 
<meta name="description" content="Dominique Thiebaut's Web Page" />
 
<meta name="description" content="Dominique Thiebaut's Web Page" />
Line 9: Line 12:
 
<meta name="robots" content="FOLLOW,INDEX" />
 
<meta name="robots" content="FOLLOW,INDEX" />
  
[[CSC231 | Back to CSC231 Main Page]]
+
 
 
<hr />
 
<hr />
  
Line 21: Line 24:
  
 
Assume that your data section is initialized with the following variables:
 
Assume that your data section is initialized with the following variables:
 
+
<br />
 +
<source lang="asm">
 
       msg    db    3,"ALL",11,"PROGRAMMERS",3,"ARE",11,"PLAYWRIGHTS"
 
       msg    db    3,"ALL",11,"PROGRAMMERS",3,"ARE",11,"PLAYWRIGHTS"
 
               db    3,"AND",3,"ALL",9,"COMPUTERS",3,"ARE",5,"LOUSY"
 
               db    3,"AND",3,"ALL",9,"COMPUTERS",3,"ARE",5,"LOUSY"
Line 27: Line 31:
 
       N      equ  10
 
       N      equ  10
  
 
+
</source>
 +
<br />
 
Note that the msg contains byte numbers followed by words. The byte number preceeding a word corresponds to the number of letters in the word. So '3,"ALL"' for example means that the word that follows 3 is a 3-character word. '11,"PROGRAMMERS"' means that the string following the byte that contains 11 is an 11-character word.
 
Note that the msg contains byte numbers followed by words. The byte number preceeding a word corresponds to the number of letters in the word. So '3,"ALL"' for example means that the word that follows 3 is a 3-character word. '11,"PROGRAMMERS"' means that the string following the byte that contains 11 is an 11-character word.
  
Line 34: Line 39:
 
Your assignment is to write a program that uses one or several loops that go ''N'' times and that print all the words on separate lines, one after the other, such that each word is '''capitalized''', i.e. its first letter is uppercase, and the others are lowercase.
 
Your assignment is to write a program that uses one or several loops that go ''N'' times and that print all the words on separate lines, one after the other, such that each word is '''capitalized''', i.e. its first letter is uppercase, and the others are lowercase.
  
Save your program in a file called hw4a.asm which you will submit as follows:
+
Save your program in a file called hw5a.asm which you will submit as follows:
  
  
           submit  hw4 hw4a.asm
+
           submit  hw5 hw5a.asm
  
  
Line 44: Line 49:
 
===Preparation===
 
===Preparation===
  
 +
<Font color="magenta">Important Note: this problem must be done on '''grendel.csc.smith.edu''', as it requires a 32-bit machine, while beowulf is a 64-bit machine.  This has to do with mixing assembly (generated in 32-bit mode) and C-programs (compiled in 64-bit on beowulf, and in 32-bit on grendel).</Font>
  
 
While printing strings of characters on the screen is relatively easy in assembly, as you saw in the previous assignment and exercises, inputing numbers and printing numbers is more difficult in assembly (we'll see why in class).
 
While printing strings of characters on the screen is relatively easy in assembly, as you saw in the previous assignment and exercises, inputing numbers and printing numbers is more difficult in assembly (we'll see why in class).
Line 57: Line 63:
 
Let's try this concept with a simple example:
 
Let's try this concept with a simple example:
  
First use your favorite editor to write the following C program and call it driver.c
+
First use your favorite editor to write the following C program and call it '''driver.c'''
 
+
<br />
 +
::<source lang="C">
 
       #include <stdio.h>
 
       #include <stdio.h>
 
   
 
   
Line 66: Line 73:
 
         asm_main();
 
         asm_main();
 
       }
 
       }
 
+
</source>
  
 
All it does is have a main program that calls a function '''asm_main()''', which will be the entry point of our assembly language program.
 
All it does is have a main program that calls a function '''asm_main()''', which will be the entry point of our assembly language program.
Line 79: Line 86:
 
       nasm -f elf -F stabs asm_io.asm
 
       nasm -f elf -F stabs asm_io.asm
  
Now enter the test program below in assembly. Call it '''hw4test.asm'''. Be careful that it is slightly different from the ones we have been writing so far in that''' the starting label and the last instructions are not the standard ones'''.
+
Now enter the test program below in assembly. Call it '''hw5test.asm'''. Be careful that it is slightly different from the ones we have been writing so far in that''' the starting label and the last instructions are not the standard ones'''.
  
       ;;; hw4test.asm
+
::<source lang="asm">
 +
       ;;; hw5test.asm
 
       ;;; a simple demo program to test I/O with
 
       ;;; a simple demo program to test I/O with
 
       ;;; a C "wrapper" program
 
       ;;; a C "wrapper" program
Line 125: Line 133:
 
   
 
   
 
               ret
 
               ret
 
+
</source>
 +
<br />
 
Note: the beginning of the program is not labeled '''_start''' any longer, but '''asm_main'''. The reason is that the start of the program is in the '''driver.c''' program, not in our assembly program. Also, the program does not end with an '''int 0x80''' instruction any longer, but by a '''ret''' instruction, so that it can return to the C program which will end with its own (hidden) '''int 0x80'''.  
 
Note: the beginning of the program is not labeled '''_start''' any longer, but '''asm_main'''. The reason is that the start of the program is in the '''driver.c''' program, not in our assembly program. Also, the program does not end with an '''int 0x80''' instruction any longer, but by a '''ret''' instruction, so that it can return to the C program which will end with its own (hidden) '''int 0x80'''.  
  
Line 134: Line 143:
 
To assemble and run your program just follow these steps:
 
To assemble and run your program just follow these steps:
  
             nasm -f elf -F stabs hw4test.asm
+
             nasm -f elf -F stabs hw5test.asm
             gcc -o hw4test driver.c asm_io.o hw4test.o  
+
             gcc -o hw5test driver.c asm_io.o hw5test.o  
             ./hw4test
+
             ./hw5test
 
   
 
   
 
             Hello! Please enter an integer number: 1234
 
             Hello! Please enter an integer number: 1234
Line 142: Line 151:
  
  
The first line assembles hw4test.asm. The second line asks the C compiler '''gcc''' to compile '''driver.c''' and to link it with the object files '''asm_io.o''' and '''hw2test.o''', and to store the executable in a file called '''hw4test'''. The last line executes the program.
+
The first line assembles hw5test.asm. The second line asks the C compiler '''gcc''' to compile '''driver.c''' and to link it with the object files '''asm_io.o''' and '''hw2test.o''', and to store the executable in a file called '''hw5test'''. The last line executes the program.
  
 
The functions provided by the asm_io.o library are described now:
 
The functions provided by the asm_io.o library are described now:
Line 158: Line 167:
 
* '''print_nl''': prints out to the screen a new line character.  
 
* '''print_nl''': prints out to the screen a new line character.  
  
The '''asm_io''' library supports also two ''macros'' that you may find useful: ''dump_regs'' and ''dump_mem''. They can be used to display the contents of the registers and the contents of memory. Try adding these two lines at the end of your '''hw4test.asm''' program:
+
The '''asm_io''' library supports also two ''macros'' that you may find useful: ''dump_regs'' and ''dump_mem''. They can be used to display the contents of the registers and the contents of memory. Try adding these two lines at the end of your '''hw5test.asm''' program:
  
 
               call    print_nl              ; call the function that prints
 
               call    print_nl              ; call the function that prints
Line 179: Line 188:
 
Your program should use an array and initialize it with 1 in the first cell, and 0 everywhere, else. Then your program prints it. It's the first row of Pascal's triangle:
 
Your program should use an array and initialize it with 1 in the first cell, and 0 everywhere, else. Then your program prints it. It's the first row of Pascal's triangle:
  
1 0 0 0 0 0 0 0 0 0
+
1 0 0 0 0 0 0 0 0 0
  
 
Then scan the array starting with the last cell (using a register pointer) and replace this cell with the sum of itself and its left neighbor:
 
Then scan the array starting with the last cell (using a register pointer) and replace this cell with the sum of itself and its left neighbor:
  
 +
::<source lang="text">
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
                    \|                    0+0 = 0
+
                      |                    0+0 = 0
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
 +
</source>
  
Keep on going "down" the array by moving the pointer left by one cell (remember that if your array is an array of word, that means decrementing the register by 2, if an array of double words, decrementing it by 4), summing up cells with their left neighbors:
+
Keep on going "down" the array by moving the pointer left by one cell (remember that if your array is an array of words, that means decrementing the register by 2, if an array of double words, decrementing it by 4), summing up cells with their left neighbors:
  
 +
::<source lang="text">
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
                  \|                  0+0 = 0
+
                    |                  0+0 = 0
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
 
   
 
   
 
   
 
   
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
                \|                    0+0 = 0
+
                  |                    0+0 = 0
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
 
   
 
   
 
   
 
   
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
              \|                      0+0 = 0
+
                |                      0+0 = 0
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
 
   
 
   
Line 206: Line 218:
 
   
 
   
 
     1 0 0 0 0 0 0 0 0 0
 
     1 0 0 0 0 0 0 0 0 0
    \|                                1+0 = 1
+
      |                                1+0 = 1
 
     1 1 0 0 0 0 0 0 0 0
 
     1 1 0 0 0 0 0 0 0 0
  
 +
</source>
  
 
You end up with the second row of Pascal's triangle:
 
You end up with the second row of Pascal's triangle:
  
 +
 +
::<source lang="text">
 
   1 1 0 0 0 0 0 0 0 0 0
 
   1 1 0 0 0 0 0 0 0 0 0
 +
</source>
  
 
which you can now print.
 
which you can now print.
Line 227: Line 243:
  
  
Format your program so that it uses the driver.c and asm_io.asm programs to print integers. Store your program in a file called '''hw4b.asm''', and submit it as follows:
+
Format your program so that it uses the driver.c and asm_io.asm programs to print integers. Store your program in a file called '''hw5b.asm''', and submit it as follows:
  
     submit hw4 hw4b.asm
+
     submit hw5 hw5b.asm
  
  

Latest revision as of 04:58, 9 April 2017

--D. Thiebaut 19:54, 20 October 2010 (UTC)


<meta name="keywords" content="computer science, assembly language, pentium, exercise, machine language, intel" /> <meta name="description" content="Dominique Thiebaut's Web Page" /> <meta name="title" content="Dominique Thiebaut -- Computer Science" /> <meta name="abstract" content="Dominique Thiebaut's Computer Science Web pages" /> <meta name="author" content="thiebaut at cs.smith.edu" /> <meta name="distribution" content="Global" /> <meta name="revisit-after" content="10 days" /> <meta name="copyright" content="(c) D. Thiebaut 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,2008" /> <meta name="robots" content="FOLLOW,INDEX" />



The assignment is due on 10/28/10 at 11:59 p.m. plus 1 minute. You can work on this assignment in pair.

Problem #1: Addressing modes and one-dimensional arrays

Assume that your data section is initialized with the following variables:

      msg     db    3,"ALL",11,"PROGRAMMERS",3,"ARE",11,"PLAYWRIGHTS"
              db    3,"AND",3,"ALL",9,"COMPUTERS",3,"ARE",5,"LOUSY"
              db    6,"ACTORS"
      N       equ   10


Note that the msg contains byte numbers followed by words. The byte number preceeding a word corresponds to the number of letters in the word. So '3,"ALL"' for example means that the word that follows 3 is a 3-character word. '11,"PROGRAMMERS"' means that the string following the byte that contains 11 is an 11-character word.

N represents the total number of words in the string msg.

Your assignment is to write a program that uses one or several loops that go N times and that print all the words on separate lines, one after the other, such that each word is capitalized, i.e. its first letter is uppercase, and the others are lowercase.

Save your program in a file called hw5a.asm which you will submit as follows:


          submit  hw5  hw5a.asm


Problem #2: Pascal's Triangle

Preparation

Important Note: this problem must be done on grendel.csc.smith.edu, as it requires a 32-bit machine, while beowulf is a 64-bit machine. This has to do with mixing assembly (generated in 32-bit mode) and C-programs (compiled in 64-bit on beowulf, and in 32-bit on grendel).

While printing strings of characters on the screen is relatively easy in assembly, as you saw in the previous assignment and exercises, inputing numbers and printing numbers is more difficult in assembly (we'll see why in class).

So, for the time being, to deal with the input/output of integers we will use a trick: we will link our assembly language program to a C program, and make the C program handle the input and output of information for us.

Don't worry if you don't know C. We will not write a single line of C code except for the small C program which will never change.

When we want to print a number from our assembly program, or when we want to get a number from the keyboard, we simply call the appropriate C function from our assembly program. Because the linker will link our program with the C program, we can call functions written in another language from assembly. This is a useful programmer trick!

It sounds complicated, but you'll see that it isn't that bad.

Let's try this concept with a simple example:

First use your favorite editor to write the following C program and call it driver.c

      #include <stdio.h>
 
      extern int asm_main( void );
 
      int main() {
        asm_main();
      }

All it does is have a main program that calls a function asm_main(), which will be the entry point of our assembly language program.

Next get a small library that will provide a simple interface between this C program and our assembly language program.

Create the object file for the library:

     nasm -f elf -F stabs asm_io.asm

Now enter the test program below in assembly. Call it hw5test.asm. Be careful that it is slightly different from the ones we have been writing so far in that the starting label and the last instructions are not the standard ones.

      ;;; hw5test.asm
      ;;; a simple demo program to test I/O with
      ;;; a C "wrapper" program
 
      %include "asm_io.inc"
 
              ;; -------------------------
              ;; data segment
              ;; -------------------------
              section .data
      msg     db      "Hello! Please enter an integer number: ",0x00
      msg2    db      "You have entered ",0x00
      x       dd      0
 
              ;; -------------------------
              ;; code area
              ;; -------------------------
              section .text
              global  asm_main
      asm_main:       
 
              mov     eax,msg               ; pass address of the string msg in eax
              call    print_string          ; call a function in asm_io library
                                            ; that will print the string msg
 
              call    read_int              ; call a function that reads an
              mov     [x], eax              ; integer from the keyboard and
                                            ; returns it in eax.  Save returned
                                            ; value in variable x
 
              mov     eax,msg2              ; print the string msg2
              call    print_string          ; ("you have entered")
 
              mov     eax,[x]               ; get integer user entered
              call    print_int             ; pass it via eax and call the
                                            ; function specialized in printing
                                            ; integer numbers
 
              call    print_nl              ; call the function that prints
                                            ; a new blank line
 
              ;; return to C program
 
              ret


Note: the beginning of the program is not labeled _start any longer, but asm_main. The reason is that the start of the program is in the driver.c program, not in our assembly program. Also, the program does not end with an int 0x80 instruction any longer, but by a ret instruction, so that it can return to the C program which will end with its own (hidden) int 0x80.

Although we haven't seen the call instruction yet, it's fairly easy to understand what it does. It forces the processor to go somewhere else in the memory, execute a piece of code, and return back to the program. We'll look at it in details later. Right now the logic of the program should be sufficient for you to see how to use these simple functions to print strings and number.

Note: in C all strings of characters must be terminated by a 0 (0x00) byte. Because here we have used a C function to print the strings of characters, we added a 0x00 byte at the end of each string. Make sure that you add 0x00 at the end of all your strings of characters if you are going to use the method shown above to print your strings.

To assemble and run your program just follow these steps:

            nasm -f elf -F stabs hw5test.asm
            gcc -o hw5test driver.c asm_io.o hw5test.o 
            ./hw5test

            Hello! Please enter an integer number: 1234
            You have entered 1234


The first line assembles hw5test.asm. The second line asks the C compiler gcc to compile driver.c and to link it with the object files asm_io.o and hw2test.o, and to store the executable in a file called hw5test. The last line executes the program.

The functions provided by the asm_io.o library are described now:

  • read_int: reads an integer from the keyboard and stores it into the EAX register.
  • print_int: prints out in 2's complement the value of the integer stored in EAX on the screen.
  • print_string: prints out to the screen the contents of the string at the address stored in EAX. The string must be terminated by a 0x00 byte (C-string).
  • print_char: prints out to the screen the character whose ASCII value is stored in AL
  • read_char: reads a single character from the keyboard and stores its ASCII code into the EAX register.
  • print_nl: prints out to the screen a new line character.

The asm_io library supports also two macros that you may find useful: dump_regs and dump_mem. They can be used to display the contents of the registers and the contents of memory. Try adding these two lines at the end of your hw5test.asm program:

             call    print_nl              ; call the function that prints
                                           ; a new blank line

             dump_regs 1
             dump_mem  1, msg, 3

              
             ;; return to C program
             ret

The first of the new lines dump_regs 1 dumps the registers and uses 1 as a label, so that if you use this macro several times in your program, you can label each one with a different number so that you can figure out from the output which macro actually output what. The second of the new lines dump_mem 1, msg, 3 output 3 lines of 16 bytes starting at the address corresponding to the variable msg, and uses 1 as the label for this output.

Programming Assignment

CSC231 PascalTriangle.gif

Write a program that outputs the first 10 rows of Pascal's Triangle.

Your program should use an array and initialize it with 1 in the first cell, and 0 everywhere, else. Then your program prints it. It's the first row of Pascal's triangle:

1 0 0 0 0 0 0 0 0 0

Then scan the array starting with the last cell (using a register pointer) and replace this cell with the sum of itself and its left neighbor:

    1 0 0 0 0 0 0 0 0 0
                      |                    0+0 = 0
    1 0 0 0 0 0 0 0 0 0

Keep on going "down" the array by moving the pointer left by one cell (remember that if your array is an array of words, that means decrementing the register by 2, if an array of double words, decrementing it by 4), summing up cells with their left neighbors:

    1 0 0 0 0 0 0 0 0 0
                    |                  0+0 = 0
    1 0 0 0 0 0 0 0 0 0
 
 
    1 0 0 0 0 0 0 0 0 0
                  |                    0+0 = 0
    1 0 0 0 0 0 0 0 0 0
 
 
    1 0 0 0 0 0 0 0 0 0
                |                      0+0 = 0
    1 0 0 0 0 0 0 0 0 0
 
    . . .
 
    1 0 0 0 0 0 0 0 0 0
      |                                1+0 = 1
    1 1 0 0 0 0 0 0 0 0

You end up with the second row of Pascal's triangle:


   1 1 0 0 0 0 0 0 0 0 0

which you can now print.

Repeat this process until you have printed all 10 rows of the triangle. Row 1 is the one with one 1 and nine 0s on it.

Your program should output the rows one above the other, including the zeros:

1 0 0 0 
1 1 0 0
1 2 1 0
1 3 3 1
...


Format your program so that it uses the driver.c and asm_io.asm programs to print integers. Store your program in a file called hw5b.asm, and submit it as follows:

   submit hw5 hw5b.asm


Hints

  1. Figure out what the largest number you will get is, and decide whether you want to use an array of bytes, words, or double words.
  2. You may want to start by initializing your array to Pascal's Row 4, for example, and transform it into Row 5, using just one loop that scans the array. Once this works, you can then add an outside loop that will make the program compute the other rows, starting with Row 0.