Difference between revisions of "CSC231 Homework 6 2017"

From dftwiki3
Jump to: navigation, search
 
(3 intermediate revisions by the same user not shown)
Line 7: Line 7:
 
</tanbox>
 
</tanbox>
 
<br />
 
<br />
<onlydft>
+
<br />
 
==Problem Statement==
 
==Problem Statement==
 
<br />
 
<br />
Write an assembly language program called '''hw6.asm''' similar to the one with work out in class, but with a few important differences, listed below.  You can find the program we wrote in class [[CSC231_Developing_the_Game_of_Life_in_Assembly | here]].
+
Write an assembly language program called '''hw6.asm''' that implements a 1-dimensional ''game of life'', similar to the one with work out in class, but with a few important differences, listed below.  You can find the program we wrote in class [[CSC231_Developing_the_Game_of_Life_in_Assembly | here]].
 
<br />
 
<br />
:# Your program will use an ''include'' file to get the array dish, which contains the initial 1-line generation of cells.   
+
:# Your program will use an ''include'' file to get the array '''dish''', which contains the initial generation of cells.   
 
:# Your program will not use a single '''loop''' instruction, and will implement all the loops using '''cmp''' and '''jump''' instructions (conditionals and unconditional jumps will be used).
 
:# Your program will not use a single '''loop''' instruction, and will implement all the loops using '''cmp''' and '''jump''' instructions (conditionals and unconditional jumps will be used).
:# Your program will not necessarily set the first and last cells of newGen to 0, as the program we wrote in class did.  The first and last cells of dish are different from the others in that they only have 1 neighbor. The first cell, at Index 0, has a neighbor in the cell at Index 1.  The last cell, at Index N-1, has one neighbor, at Index N-2.  While our program automatically decided that the first and last cells would die in the next generation, your program won't.  Instead it will see if these boundary cells have 1 live neighbor or not, and if they do have a live neighbor in dish, will make them live in newGen.
+
:# Your program will not necessarily set the first and last cells of newGen to 0, as the program we wrote in class did.  The first and last cells of dish are different from the others in that they only have 1 neighbor.   While our program automatically decided that the first and last cells would die in the next generation, your program won't.  Instead it will see if these boundary cells have 1 live neighbor or not, and if they do, will make them live in newGen.
 
<br />
 
<br />
 
==Using an Include File==
 
==Using an Include File==
 
<br />
 
<br />
The concept is simple: you put part of the code into a separate file, and you use an "''%include''"  statement inside the main program to tell nasm that it should read the contents of the include file as part of this program.
+
The concept of an include file is simple: you put part of the code into a separate file, and you use an "''%include''"  statement inside the main program to tell nasm that it should read the contents of the include file as part of this program.
 
<br />
 
<br />
 
The code below illustrates how this is done.  We have two files:
 
The code below illustrates how this is done.  We have two files:
Line 152: Line 152:
 
<br />
 
<br />
 
I have created a program called '''evaluateHw6.sh''' to test your '''hw6.asm''' program.  It will give you some information relative to whether your program is output the correct generations or not.
 
I have created a program called '''evaluateHw6.sh''' to test your '''hw6.asm''' program.  It will give you some information relative to whether your program is output the correct generations or not.
</onlydft>
+
<br />
 +
Just type:
 +
 +
evaluateHw6.sh
 +
 +
on the command line to test your program.
 +
 
 +
You may have guessed why this assignment is asking you to write a two-file program.  It is because by doing so, your hw6.asm code can be tested with different initial dish contents, and for different many generations, '''without''' having to change your program.  Only the ''dishArray.inc'' file needs to be changed. 
 +
<br />
 +
This is what the evaluateHw6.sh program does: it makes a copy of your hw6.asm program in a new directory, puts there a different, unknown (to you) dishArray.inc file, assembles and links the two, and run the resulting executable, comparing its output to the output of the solution program.
 +
<br />
 +
==Submission==
 +
<br />
 +
* Submit your program on Moodle, in the Homework 6 section.
 +
 
 
<br />
 
<br />
 
<br />
 
<br />

Latest revision as of 09:54, 3 April 2017

--D. Thiebaut (talk) 18:56, 1 April 2017 (EDT)


Game Of Life Without Loop Instructions


For this assignment, you need to write a game of life program in assembly, and the challenge is to implement it without using the loop instruction, using only the cmp instruction and conditional jumps.



Problem Statement


Write an assembly language program called hw6.asm that implements a 1-dimensional game of life, similar to the one with work out in class, but with a few important differences, listed below. You can find the program we wrote in class here.

  1. Your program will use an include file to get the array dish, which contains the initial generation of cells.
  2. Your program will not use a single loop instruction, and will implement all the loops using cmp and jump instructions (conditionals and unconditional jumps will be used).
  3. Your program will not necessarily set the first and last cells of newGen to 0, as the program we wrote in class did. The first and last cells of dish are different from the others in that they only have 1 neighbor. While our program automatically decided that the first and last cells would die in the next generation, your program won't. Instead it will see if these boundary cells have 1 live neighbor or not, and if they do, will make them live in newGen.


Using an Include File


The concept of an include file is simple: you put part of the code into a separate file, and you use an "%include" statement inside the main program to tell nasm that it should read the contents of the include file as part of this program.
The code below illustrates how this is done. We have two files:

GameOfLifeDemo.asm
That's the main program. It contains the data section and the code section. In the data section is a statement %include "dishArray.inc that instructs nasm to read this other file
dishArray.inc
This file contains the definitions of
  • the dish array,
  • the constant N, and
  • the number of generations maxGen.


demo.asm


;;; ; demo.asm
;;; ; Authors: D. Thiebaut and CSC231 Class
;;; ;
;;; ; Demo program illustrating how to 
;;; ; use an include file to feed the dish
;;; ; array to the program.
;;; ;
;;; ; to assemble and run:
;;; ;
;;; ;     nasm -f elf -F  stabs demo.asm
;;; ;     ld -melf_i386 -o demo demo.o
;;; ;     ./demo
;;; ; -------------------------------------------------------------------


;;;  ------------------------------------------------------------
;;;  data areas
;;;  ------------------------------------------------------------

	        section .data
;;; the current dish with its cells.  We use 0 and 1 to
;;; indicate dead and live cells, respectively.
%include	"dishArray.inc"

;;; the new generation of cells.  That's the "future" of the
;;; cells in the dish.  We make it the same size as dish, and
;;; fill it with N dead cells.
	
newGen	        times   N db 0
	
;;; dishP is a string that will contain ' ' or '!' for
;;; each 0 or 1 in dish.  
dishP		times   N  db ' '
		db	10			; add a \n at the end
						;  of dishP
	
generation	dd	0			; save ecx from for generation loop
i		dd	0			; used by for loops
	
;;;  ------------------------------------------------------------
;;;  code area
;;;  ------------------------------------------------------------

	        section .text
	        global  _start

_start:
main:	
;;; -------------------------------------------------------------
;;; print( dish )
		;; first we copy dish into dishP and at the same
		;; time replace 0 by ' ' and 1 by '!'

;;; for i in range( N ):
		mov	esi, dish 
		mov	edi, dishP

		mov	dword[i], 0
forPrint:	cmp	dword[i], N
		jge	forPrintEnd
	
		mov	al, byte[esi]
		add	al, ' '			;0 becomes ' ', 1 becomes '!'
		mov	byte[edi], al
		inc	esi			;esi points to next byte in dish
		inc	edi			;edi points to next byte in dispP

		;; i++, loop back
		inc	dword[i]
		jmp	forPrint
forPrintEnd:	
	
		;; print dishP as a string.
		mov	eax, 4			;prints dishP to screen
		mov	ebx, 1
		mov	ecx, dishP 		;dishP address
		mov	edx, N+1		;+1 to include the \n
		int	0x80

	
;;;  exit()
exit:		mov     eax,1
	        mov     ebx,0
	        int     0x80	; final system call


dishArray.inc


padding0        db      0
dish            db      1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
                db      1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0
                db      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
N               equ     $-dish
padding1        db      0

maxGen          dd      10


  • The variables padding0 and padding1 are extra 0 bytes around the array dish. They will always be there around the array, and if you can make use of them in your program, please do so. Otherwise, please ignore them.
  • N is a nasm constant that is equal to the number of bytes (or cells) in dish.
  • maxGen is the maximum number of generations your program should output. Since the program prints the initial generation of cells plus maxGen generations, the total number of lines your program will output should be equal to maxGen + 1.

Note that in the Game of Life program we generated in class together, we used 20 as the number of generations. In your new version, you shouldn't use a constant, but rather whatever number is in the int variable maxGen.

Running the Demo Program


 231b@aurora ~ $ nasm -f elf demo.asm
 231b@aurora ~ $ ld -melf_i386 demo.o -o demo
 231b@aurora ~ $ ./demo
 !               ! ! ! ! ! ! ! !                !

  • You should verify that it prints the ASCII version of the dish array defined in the dishArray.inc file.
  • For fun, modify the 0s and 1s inside the array dish, in the dishArray.inc file (you may remove some, or add new 1s or 0s), and assemble, link, and run the demo program again. You should see the new output reflect your changes.
  • Similarly, change the number stored in maxGen, in dishArray.inc, re-assemble, link, and execute, and see how your change affects the output.


Testing Your Program


I have created a program called evaluateHw6.sh to test your hw6.asm program. It will give you some information relative to whether your program is output the correct generations or not.
Just type:

evaluateHw6.sh

on the command line to test your program.

You may have guessed why this assignment is asking you to write a two-file program. It is because by doing so, your hw6.asm code can be tested with different initial dish contents, and for different many generations, without having to change your program. Only the dishArray.inc file needs to be changed.
This is what the evaluateHw6.sh program does: it makes a copy of your hw6.asm program in a new directory, puts there a different, unknown (to you) dishArray.inc file, assembles and links the two, and run the resulting executable, comparing its output to the output of the solution program.

Submission


  • Submit your program on Moodle, in the Homework 6 section.