Skip to content

Instantly share code, notes, and snippets.

@Ricket
Created February 23, 2017 04:01
Show Gist options
  • Save Ricket/f6028390ddd3591c8d375b796443c09b to your computer and use it in GitHub Desktop.
Save Ricket/f6028390ddd3591c8d375b796443c09b to your computer and use it in GitHub Desktop.
CSC236 Assembly -- game of life assignment
;--------------------------------------------------------------
; 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