Created
February 23, 2017 04:01
-
-
Save Ricket/f6028390ddd3591c8d375b796443c09b to your computer and use it in GitHub Desktop.
CSC236 Assembly -- game of life assignment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;-------------------------------------------------------------- | |
; Program: nextgen subroutine *** MASM VERSION *** | |
; | |
; Function: Calculates the next generation for the game of life | |
; | |
; Input: Two pointers | |
; - old generation pointer at bp+4 | |
; - new generation pointer at bp+6 | |
; | |
; Output: New generation data created | |
; | |
; Owner: Dana Lasher | |
; Student: Richard Carter | |
; | |
; Date: Update_Reason | |
; ------------------------- | |
; 12/23/2008 Original version | |
; 04/17/2009 Awesome version | |
; | |
; My algorithm loops through each cell, counting the cell's neighbors. Then | |
; it loops through the neighbors array and determines the next generation | |
; based on the Game of Life logic. This is a different algorithm from the | |
; C source code given in the specs, which performed both steps at once. | |
; | |
;--------------------------------------- | |
.model small ;64k code and 64k data | |
.8086 ;only allow 8086 instructions | |
public _nextgen ;allow external programs to call | |
;--------------------------------------- | |
.data ;start the data segment | |
;--------------------------------------- | |
count dw ? ;count of elements | |
neighbors db 100 dup(0) ;count of neighbors of each cell | |
;--------------------------------------- | |
; The bx_ table is a table of offsets to the neighboring cells. | |
; For example, the top left cell loops through bx_tl. It checks | |
; for its neighbor to the right (index+1), bottom right (+11), | |
; and below (+10). | |
;--------------------------------------- | |
bx_tl dw 1,11,10,0 | |
bx_t dw -1,1,9,10,11,0 | |
bx_tr dw -1,9,10,0 | |
bx_l dw -10,-9,1,11,10,0 | |
bx_m dw -11,-10,-9,-1,1,9 | |
dw 10,11,0 | |
bx_r dw -10,-11,-1,9,10,0 | |
bx_bl dw -10,-9,1,0 | |
bx_b dw -1,-11,-10,-9,1,0 | |
bx_br dw -1,-11,-10,0 | |
;--------------------------------------- | |
; The c_ table is a jump table for each of the types of cells. | |
; It dictates how many times the check loop should be executed, | |
; and each iteration of the loop refers to the corresponding entry | |
; in the bx_ table above. | |
;--------------------------------------- | |
c_tl dw neighborcheck,neighborcheck,neighborcheck,countloop | |
c_t dw neighborcheck,neighborcheck,neighborcheck,neighborcheck | |
dw neighborcheck,countloop | |
c_tr dw neighborcheck,neighborcheck,neighborcheck,countloop | |
c_l dw neighborcheck,neighborcheck,neighborcheck,neighborcheck | |
dw neighborcheck,countloop | |
c_m dw neighborcheck,neighborcheck,neighborcheck,neighborcheck | |
dw neighborcheck,neighborcheck | |
dw neighborcheck,neighborcheck,countloop | |
c_r dw neighborcheck,neighborcheck,neighborcheck,neighborcheck | |
dw neighborcheck,countloop | |
c_bl dw neighborcheck,neighborcheck,neighborcheck,countloop | |
c_b dw neighborcheck,neighborcheck,neighborcheck,neighborcheck | |
dw neighborcheck,countloop | |
c_br dw neighborcheck,neighborcheck,neighborcheck,countloop | |
;--------------------------------------- | |
; The jmplsts is a jump table of jump tables. There are 100 entries, | |
; one per cell, and each entry corresponds to a jump table above for | |
; that particular cell. This dictates the neighbors that a cell has, | |
; so that an edge cell doesn't do any checks for nonexistent neighbors. | |
;--------------------------------------- | |
jmplsts dw c_tl,8 dup(c_t),c_tr | |
dw 8 dup(c_l,8 dup(c_m),c_r) | |
dw c_bl,8 dup(c_b),c_br | |
;--------------------------------------- | |
.code ;start the code segment | |
;--------------------------------------- | |
; Save the registers. C/C++ requires: bp si di | |
; Get the pointers to the old and new generations. | |
;--------------------------------------- | |
_nextgen: ; | |
push bp ;save bp register | |
mov bp,sp ;set bp to point to stack | |
push si ;save si | |
push di ;save di | |
mov si,[bp+4] ;si points to the old generation | |
mov di,[bp+6] ;di points to the new generation | |
;--------------------------------------- | |
;--------------------------------------- | |
; | |
; This is the code to calculate the new generation. | |
; | |
; It is super awesome! | |
; | |
;--------------------------------------- | |
; *until timetogen, di = jumplist pointer* | |
mov dx,100 ;init cell offset | |
countloop: ; | |
dec dx ;decrement offset counter | |
js timetogen ;if dx < 0, go to generation step | |
; | |
mov bx,dx ;retrieve bx | |
; | |
mov byte ptr [neighbors+bx],0 ;init neighbor count to 0 | |
; | |
add bx,bx ;double bx | |
mov di,word ptr [jmplsts+bx] ;get di ready with the jump dest | |
mov bx,dx ;restore bx | |
jmp word ptr [di] ;and jump to the dest | |
;--------------------------------------- | |
; "neighborcheck" is one neighbor check. | |
; | |
; It utilizes the tables in data space to get what it's checking, and whether | |
; to jump back to another check or to the top of the loop after the check. | |
;--------------------------------------- | |
neighborcheck: ; | |
add bx,word ptr [di-98] ;offset the cell pointer from the table | |
;(bx_*) - 98 is the distance from the | |
;c_* table to the bx_* table. | |
cmp byte ptr [si+bx],'*';is that neighbor cell alive? | |
mov bx,dx ;..restore bx | |
jne neighborcheck_ ;if neighbor is not dead, | |
add byte ptr [neighbors+bx],1; add 1 to neighbor count | |
neighborcheck_: ; | |
add di,2 ;point to the next entry in jump table | |
jmp word ptr [di] ;and jump to it. | |
;--------------------------------------- | |
;--------------------------------------- | |
; All neighbor counts have been calculated. Now we use the counts to determine | |
; the next generation. | |
;--------------------------------------- | |
timetogen: ; | |
; | |
mov di,[bp+6] ;di = next generation pointer | |
mov bx,99 ;bx = counter and base register | |
;--------------------------------------- | |
; Loop through each cell | |
;--------------------------------------- | |
nextgenloop: ; | |
cmp byte ptr [si+bx],'*';if current cell != '*' | |
jne cell_dead ; then jump to cell_dead | |
; | |
cell_alive: ; | |
cmp byte ptr [neighbors+bx],2 ;how many neighbors? | |
jb kill ;< 2: kill the cell | |
je survive ;==2: the cell lives another generation | |
cell_dead:;(or alive but > 2 neighbors) ; | |
cmp byte ptr [neighbors+bx],3 ;how many neighbors? | |
je survive ;==3: the cell springs to life, or lives | |
; | |
kill: ;kill (or keep dead) | |
mov byte ptr [di+bx],' '; put a space (dead cell) | |
jmp _genloop ; and loop | |
; | |
survive: ;live (or let live) | |
mov byte ptr [di+bx],'*'; put a * | |
; | |
_genloop: ; | |
dec bx ;decrement the counter/pointer | |
jns nextgenloop ;and loop if not negative | |
;--------------------------------------- | |
;--------------------------------------- | |
; Restore registers and return. | |
;--------------------------------------- | |
exit: ; | |
pop di ;restore di | |
pop si ;restore si | |
pop bp ;restore bp | |
ret ;return | |
;--------------------------------------- | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment