CSC231 Homework 9 Solutions
--D. Thiebaut 11:55, 20 November 2012 (EST)
Programming
;;; hw9.asm
;;; Naomi Long
;;; 231a-ad
;;;
;;; Plays game of life 20 times with 1D array of 70 orgs. Displays
;;; dead organisms as '.' and live ones as 'o'. First and last orgs
;;; in org array represent outside boundaries and are always dead.
;;;
;;; Takes initial org array and updates it based on 3 rules of life.
;;; 1. If two dead neighbors, org dies. 2. If two live neighbors,
;;; org dies. 3. If one dead and one live neighbor, lives.
;;;
;;; Sample output cut down for space, sandwiched between two prompts:
;;; [231a-ad@grendel ~/hw9]$ ./hw9
;;; o.o....oo....o......o.........
;;; ...o..oooo..o.o....o.o........
;;; ..o.ooo..ooo...o..o...o.......
;;; .o..o.oooo.oo.o.oo.o.o.o......
;;; o.oo..o..o.oo...oo......o.....
;;; [231a-ad@grendel ~/hw9]$
;;;
;;; To run:
;;; nasm -f elf -F stabs hw9.asm ; ld -melf_i386 -o hw9 hw9.o ; ./hw9
;;; -------------------------
;;; data segment
;;; -------------------------
section .data
fate db 0,1,0 ; fate table for future org statuses
orgs db 0,1,0,1,0,0,0,0,1,1 ; initial org statues, first and
db 0,0,0,0,1,0,0,0,0,0 ; last orgs count as boundaries
db 0,1,0,0,0,0,0,0,0,0
db 0,0,0,1,0,1,0,0,0,1
db 0,0,0,0,0,0,0,0,0,1
db 0,1,0,0,0,1,0,0,0,0
db 1,0,1,0,0,1,0,0,1,0
numOrgs equ $-orgs-2 ; number of orgs mins boundaries
temp db 0,0,0,0,0,0,0,0,0,0 ; stores temp new status for updating
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
chars db ".","o" ; chars representing dead and live orgs
newline db 10
;;; -------------------------
;;; code area
;;; -------------------------
section .text
global _start:
_start:
push dword numOrgs
push dword orgs
push dword chars
call printStatus ; print initial arrangement of orgs
push dword newline
call printNewLine ; print new line
mov ecx, 20 ; play game of life 20 times
.playGame:
push dword numOrgs
push dword orgs
push dword temp
call update ; changes orgs by conway's rules
push dword numOrgs
push dword orgs
push dword chars
call printStatus ; print current arrangement of orgs
push dword newline
call printNewLine ; print new line
loop .playGame
;;; exit
mov ebx, 0
mov eax, 1
int 0x80
;;; ---------------------------------------------------
;;; update
;;; Updates org statuses based on rules of game. Doesn't
;;; iterate over first and last orgs, which represent
;;; outside boundaries and are always dead. Takes 3
;;; dword parameters: number of orgs in array, addrs
;;; of org array, and addrs of temp array. Doesn't
;;; modify any registers.
;;; ---------------------------------------------------
update:
push ebp ; save caller's ebp
mov ebp, esp
pushad
mov eax, 0 ; clear eax
mov ecx, dword[ebp+16] ; update all orgs
mov ebx, dword[ebp+12] ; ebx = addrs of first org
mov edx, dword[ebp+8] ; edx = addrs of first temp storage cell
.for:
inc ebx ; ebx points to next org
inc edx ; edx points to next temp storage cell
sub esp, 4 ; make space for return value
push ebx ; push addrs of current org
call getFate ; get new status of org
pop eax ; eax = returned new org status
mov byte[edx], al ; stores new status in temp storage
; to avoid updating based on new statuses
loop .for
push dword[ebp+16]
push dword[ebp+12]
push dword[ebp+8]
call moveTempToOrgs ; moves updated temp statuses to org array
popad
pop ebp ; restore caller's ebp
ret 3*4 ; destroy 3 dword stack frame
;;; ---------------------------------------------------
;;; getFate
;;; Takes a stack frame holding dword space for return
;;; value and dword addrs of next org. Gets fate of
;;; passed org and stores its new status in return
;;; value. Then destroys stack frame except return value.
;;; Doesn't modify any registers.
;;; ---------------------------------------------------
getFate:
push ebp ; save caller's ebp
mov ebp, esp ; ebp points to current stack position
push eax ; save eax
push ebx ; save ebx
mov ebx, 0 ; clear ebx
mov eax, dword[ebp+8] ; eax = addrs of current org
mov bl, byte[eax-1] ; bl = status of org to left
add bl, byte[eax+1] ; bl = left org status + right org status
mov bl, byte[fate+ebx] ; get new status according to rules
mov dword[ebp+12], ebx ; store return value of new status in stack
pop ebx ; restore ebx
pop eax ; restore eax
pop ebp ; restore caller's ebp
ret 1*4 ; destorys allocated stack frame but not return value
;;; ---------------------------------------------------
;;; moveTempToOrgs
;;; Moves statuses in temp array to orgs. Doesn't
;;; modify registers. Takes 3 dword parameters:
;;; number of orgs in arrays, addrs of orgs array, and
;;; addrs of temp array.
;;; ---------------------------------------------------
moveTempToOrgs:
push ebp ; save caller's ebp
mov ebp, esp
pushad
mov ecx, dword[ebp+16] ; loop over all orgs
mov ebx, dword[ebp+12] ; ebx = orgs addrs
mov edx, dword[ebp+8] ; edx = temp addrs
mov eax, 0 ; clear eax
.for:
inc ebx
inc edx
mov al, byte[edx] ; eax = current temp status
mov byte[ebx], al ; stores eax in current org
loop .for
popad
pop ebp ; restore caller's ebp
ret 3*4 ; destroy 3 dword stack frame
;;; ---------------------------------------------------
;;; printStatus
;;; Prints orgs as chars "." and "o", if alive or dead,
;;; respectively. Doesn't print boundaries (first and
;;; last members. Takes 3 dword parameters: number of
;;; orgs to print, addrs of org array, and addrs of
;;; representation chars. Destroys stack frame when
;;; done. Doesn't modify registers.
;;; ---------------------------------------------------
printStatus:
push ebp ; saves caller's ebp
mov ebp, esp
pushad
mov ecx, dword[ebp+16] ; ecx = num of orgs, will print all orgs in array
mov eax, dword[ebp+12] ; eax = addrs of orgs
mov ebx, dword[ebp+8] ; ebx = addrs of chars
.for:
push ecx ; save current iteration
mov ecx, 0 ; clear ecx
inc eax ; eax points to current org
mov cl, byte[eax] ; get status of org, 0 or 1
add ecx, ebx ; gets representation char, '.' or 'o'
push eax ; save current addrs of orgs
push ebx ; save chars addrs
mov eax, 4
mov ebx, 1
mov edx, 1
int 0x80 ; print current org status
pop ebx ; restore chars addrs
pop eax ; restore current addrs of orgs
pop ecx ; get current iteration
loop .for ; print all orgs in array
popad
pop ebp ; restores caller's ebp
ret 3*4 ; destroys 3 dword stack frame
;;; ---------------------------------------------------
;;; printNewLine
;;; Prints a new line. Takes addrs of newline character
;;; as paramater pushed in stack. Destroys stack frame
;;; afterwards. Doesn't modify registers.
;;; ---------------------------------------------------
printNewLine:
push ebp ; save caller's ebp
mov ebp, esp
pushad
mov eax, 4
mov ebx, 1
mov ecx, dword[ebp+8] ; points to new line char on stack
mov edx, 1
int 0x80
popad
pop ebp ; restore caller's ebp
ret 1*4