Instructions
Objective
Write a assembly language assignment program that allows users to manipulate 2D arrays.
Requirements and Specifications


Screenshots of output




Source Code
;***********************************************************
; Programming Assignment 4
; Student Name:
; UT Eid:
; -------------------Save Simba (Part II)---------------------
; This is the starter code. You are given the main program
; and some declarations. The subroutines you are responsible for
; are given as empty stubs at the bottom. Follow the contract.
; You are free to rearrange your subroutines if the need were to
; arise.
;***********************************************************
.ORIG x4000
;***********************************************************
; Main Program
;***********************************************************
JSR DISPLAY_JUNGLE
LEA R0, JUNGLE_INITIAL
TRAP x22
LDI R0,BLOCKS
JSR LOAD_JUNGLE
JSR DISPLAY_JUNGLE
LEA R0, JUNGLE_LOADED
TRAP x22 ; output end message
HOMEBOUND
LEA R0,PROMPT
TRAP x22
TRAP x20 ; get a character from keyboard into R0
TRAP x21 ; echo character entered
LD R3, ASCII_Q_COMPLEMENT ; load the 2's complement of ASCII 'Q'
ADD R3, R0, R3 ; compare the first character with 'Q'
BRz EXIT ; if input was 'Q', exit
;; call a converter to convert i,j,k,l to up(0) left(1),down(2),right(3) respectively
JSR IS_INPUT_VALID
ADD R2, R2, #0 ; R2 will be zero if the move was valid
BRz VALID_INPUT
LEA R0, INVALID_MOVE_STRING ; if the input was invalid, output corresponding
TRAP x22 ; message and go back to prompt
BR HOMEBOUND
VALID_INPUT
JSR APPLY_MOVE ; apply the move (Input in R0)
JSR DISPLAY_JUNGLE
JSR IS_SIMBA_HOME
ADD R2, R2, #0 ; R2 will be zero if Simba reached Home
BRnp HOMEBOUND ; otherwise, loop back
EXIT
LEA R0, GOODBYE_STRING
TRAP x22 ; output a goodbye message
TRAP x25 ; halt
JUNGLE_LOADED .STRINGZ "\nJungle Loaded\n"
JUNGLE_INITIAL .STRINGZ "\nJungle Initial\n"
ASCII_Q_COMPLEMENT .FILL x-71 ; two's complement of ASCII code for 'q'
PROMPT .STRINGZ "\nEnter Move \n\t(up(i) left(j),down(k),right(l)): "
INVALID_MOVE_STRING .STRINGZ "\nInvalid Input (ijkl)\n"
GOODBYE_STRING .STRINGZ "\nYou Saved Simba !Goodbye!\n"
BLOCKS .FILL x5000
;***********************************************************
; Global constants used in program
;***********************************************************
;***********************************************************
; This is the data structure for the Jungle grid
;***********************************************************
GRID .STRINGZ "+-+-+-+-+-+-+-+-+"
.STRINGZ "| | | | | | | | |"
.STRINGZ "+-+-+-+-+-+-+-+-+"
.STRINGZ "| | | | | | | | |"
.STRINGZ "+-+-+-+-+-+-+-+-+"
.STRINGZ "| | | | | | | | |"
.STRINGZ "+-+-+-+-+-+-+-+-+"
.STRINGZ "| | | | | | | | |"
.STRINGZ "+-+-+-+-+-+-+-+-+"
.STRINGZ "| | | | | | | | |"
.STRINGZ "+-+-+-+-+-+-+-+-+"
.STRINGZ "| | | | | | | | |"
.STRINGZ "+-+-+-+-+-+-+-+-+"
.STRINGZ "| | | | | | | | |"
.STRINGZ "+-+-+-+-+-+-+-+-+"
.STRINGZ "| | | | | | | | |"
.STRINGZ "+-+-+-+-+-+-+-+-+"
;***********************************************************
; this data stores the state of current position of Simba and his Home
;***********************************************************
CURRENT_ROW .BLKW #1 ; row position of Simba
CURRENT_COL .BLKW #1 ; col position of Simba
HOME_ROW .BLKW #1 ; Home coordinates (row and col)
HOME_COL .BLKW #1
;***********************************************************
;***********************************************************
;***********************************************************
;***********************************************************
;***********************************************************
;***********************************************************
; The code above is provided for you.
; DO NOT MODIFY THE CODE ABOVE THIS LINE.
;***********************************************************
;***********************************************************
;***********************************************************
;***********************************************************
;***********************************************************
;***********************************************************
;***********************************************************
;***********************************************************
; DISPLAY_JUNGLE
; Displays the current state of the Jungle Grid
; This can be called initially to display the un-populated jungle
; OR after populating it, to indicate where Simba is (*), any
; Hyena's(#) are, and Simba's Home (H).
; Input: None
; Output: None
; Notes: The displayed grid must have the row and column numbers
;***********************************************************
DISPLAY_JUNGLE
ADD R6, R6, #-7 ; allocate space in stack for registers
STR R0, R6, #0 ; save R0 on stack
STR R1, R6, #1 ; save R1 on stack
STR R2, R6, #2 ; save R2 on stack
STR R3, R6, #3 ; save R3 on stack
STR R4, R6, #4 ; save R4 on stack
STR R5, R6, #5 ; save R5 on stack
STR R7, R6, #6 ; save R7 on stack
LEA R0, COLHEADER ; print the column header
TRAP x22
LD R1, GRIDPTR ; load grid address
AND R2, R2, #0 ; row number
LD R3, ROWWID ; load grid row width
ROWLOOP
; print the row start spaces
LD R0, SPACE ; load space char
TRAP x21 ; print space
TRAP x21 ; print space
ADD R0, R1, #0 ; load current grid row pointer
TRAP x22 ; print row
ADD R1, R1, R3 ; advance to next row
LD R0, NEWLINE ; load newline char
TRAP x21 ; print newline
LD R0, ASCII0 ; load ascii 0
ADD R0, R0, R2 ; convert row number to ascii
TRAP x21 ; print row number
LD R0, SPACE ; load space char
TRAP x21 ; print space
ADD R0, R1, #0 ; load current grid row pointer
TRAP x22 ; print row
ADD R1, R1, R3 ; advance to next row
LD R0, NEWLINE ; load newline char
TRAP x21 ; print newline
ADD R2, R2, #1 ; increment row number
ADD R0, R2, #-8 ; compare row with 8
BRn ROWLOOP ; repeat loop while col < 8
LD R0, SPACE ; load space char
TRAP x21 ; print space
TRAP x21 ; print space
ADD R0, R1, #0 ; load current grid row pointer
TRAP x22 ; print row
LD R0, NEWLINE ; load newline char
TRAP x21 ; print newline
LDR R0, R6, #0 ; load R0
LDR R1, R6, #1 ; load R1
LDR R2, R6, #2 ; load R2
LDR R3, R6, #3 ; load R3
LDR R4, R6, #4 ; load R4
LDR R5, R6, #5 ; load R5
LDR R7, R6, #6 ; load R7
ADD R6, R6, #7 ; restore stack pointer
JMP R7
COLHEADER .STRINGZ "\n 0 1 2 3 4 5 6 7 \n"
SPACE .FILL x20
NEWLINE .FILL x0A
ASCII0 .FILL x30
ROWWID .FILL x12
GRIDPTR .FILL GRID
;***********************************************************
; LOAD_JUNGLE
; Input: R0 has the address of the head of a linked list of
; gridblock records. Each record has four fields:
; 0. Address of the next gridblock in the list
; 1. row # (0-7)
; 2. col # (0-7)
; 3. Symbol (can be I->Initial,H->Home or #->Hyena)
; The list is guaranteed to:
; * have only one Inital and one Home gridblock
; * have zero or more gridboxes with Hyenas
; * be terminated by a gridblock whose next address
; field is a zero
; Output: None
; This function loads the JUNGLE from a linked list by inserting
; the appropriate characters in boxes (I(*),#,H)
; You must also change the contents of these
; locations:
; 1. (CURRENT_ROW, CURRENT_COL) to hold the (row, col)
; numbers of Simba's Initial gridblock
; 2. (HOME_ROW, HOME_COL) to hold the (row, col)
; numbers of the Home gridblock
;
;***********************************************************
LOAD_JUNGLE
ADD R6, R6, #-7 ; allocate space in stack for R7
STR R0, R6, #0 ; save R0 on stack
STR R1, R6, #1 ; save R1 on stack
STR R2, R6, #2 ; save R2 on stack
STR R3, R6, #3 ; save R3 on stack
STR R4, R6, #4 ; save R4 on stack
STR R5, R6, #5 ; save R5 on stack
STR R7, R6, #6 ; save R7 on stack
ADD R3, R0, #0 ; save head address in R3
WHILE1
ADD R3, R3, #0 ; see if node is null
BRz ENDWHILE ; if null, end loop
LDR R1, R3, #1 ; load row
LDR R2, R3, #2 ; load column
JSR GRID_ADDRESS ; load address in grid
LDR R2, R3, #3 ; load node character
STR R2, R0, #0 ; save character in grid
NOT R2, R2 ; take one's complement
ADD R2, R2, #1 ; take two's complement (negative)
LD R1, INITIAL ; load initial char
ADD R1, R1, R2 ; compare character with initial
BRnp IFHOME ; if not equal, see if it's home
LD R1, ASTER ; load asterisk character
STR R1, R0, #0 ; save character in grid
LDR R1, R3, #1 ; load row
LEA R0, CURRENT_ROW ; load current row pointer
STR R1, R0, #0 ; save row
LDR R1, R3, #2 ; load column
LEA R0, CURRENT_COL ; load current column pointer
STR R1, R0, #0 ; save column
BR NEXT ; go to next node
IFHOME
LD R1, HOME ; load home char
ADD R1, R1, R2 ; compare character with home
BRnp NEXT ; if not equal, go to next node
LDR R1, R3, #1 ; load row
LEA R0, HOME_ROW ; load home row pointer
STR R1, R0, #0 ; save row
LDR R1, R3, #2 ; load column
LEA R0, HOME_COL ; load home column pointer
STR R1, R0, #0 ; save column
NEXT
LDR R3, R3, #0 ; load next node
BR WHILE1 ; repeat loopENDWHILE
LDR R0, R6, #0 ; load R0
LDR R1, R6, #1 ; load R1
LDR R2, R6, #2 ; load R2
LDR R3, R6, #3 ; load R3
LDR R4, R6, #4 ; load R4
LDR R5, R6, #5 ; load R5
LDR R7, R6, #6 ; load R7
ADD R6, R6, #7 ; restore stack pointer
JMP R7
HYENA .FILL x23
ASTER .FILL x2A
HOME .FILL x48
INITIAL .FILL x49
;***********************************************************
; GRID_ADDRESS
; Input: R1 has the row number (0-7)
; R2 has the column number (0-7)
; Output: R0 has the corresponding address of the space in the GRID
; Notes: This is a key routine. It translates the (row, col) logical
; GRID coordinates of a gridblock to the physical address in
; the GRID memory.
;***********************************************************
GRID_ADDRESS
ADD R6, R6, #-2 ; allocate space in stack for registers
STR R1, R6, #0 ; save R1 on stack
STR R2, R6, #1 ; save R2 on stack
ADD R0, R1, R1 ; multiply row * 2
ADD R1, R0, R0 ; multiply row * 4
ADD R1, R1, R1 ; multiply row * 8
ADD R1, R1, R1 ; multiply row * 16
ADD R1, R1, R0 ; add row*16 + row*2 = row*18
ADD R1, R1, R1 ; multiply row * 36
LD R0, ROWWID ; load row width
ADD R1, R1, R0 ; add row*36 + 18 to get row offset in grid
ADD R2, R2, R2 ; multiply column*2
ADD R2, R2, #1 ; add column*2 + 1
ADD R1, R1, R2 ; add row*36 + 18 + column*2 + 1 to get offset of (row, col)
LD R0, GRIDPTR ; load grid address
ADD R0, R0, R1 ; add grid address to offset to get required address
LDR R1, R6, #0 ; load R1
LDR R2, R6, #1 ; load R2
ADD R6, R6, #2 ; restore stack pointer
JMP R7
;***********************************************************
; IS_INPUT_VALID
; Input: R0 has the move (character i,j,k,l)
; Output: R2 zero if valid; -1 if invalid
; Notes: Validates move to make sure it is one of i,j,k,l
; Only checks if a valid character is entered
;***********************************************************
IS_INPUT_VALID
ADD R6, R6, #-2 ; allocate space in stack for R7
STR R0, R6, #0 ; save R0 on stack
STR R1, R6, #1 ; save R1 on stack
AND R2, R2, #0
NOT R2, R2
LD R1, ASCII_I_COMPLEMENT ; load the 2's complement of ASCII 'i'
ADD R1, R0, R1 ; compare the first character with 'i'
BRn INVALID ; if input was <'i', return -1
LD R1, ASCII_M_COMPLEMENT ; load the 2's complement of ASCII 'l'
ADD R1, R0, R1 ; compare the first character with 'l'
BRp INVALID ; if input was >'l', return -1
NOT R2, R2
INVALID
LDR R0, R6, #0 ; load R0
LDR R1, R6, #1 ; load R1
ADD R6, R6, #2 ; restore stack pointer
JMP R7
ASCII_I_COMPLEMENT .FILL x-69 ; two's complement of ASCII code for 'i'
ASCII_M_COMPLEMENT .FILL x-6c ; two's complement of ASCII code for 'l'
;***********************************************************
; SAFE_MOVE
; Input: R0 has 'i','j','k','l'
; Output: R1, R2 have the new row and col if the move is safe
; If the move is unsafe, that is, the move would
; take Simba to a Hyena or outside the Grid then
; return R1=-1
; Notes: Translates user entered move to actual row and column
; Also checks the contents of the intended space to
; move to in determining if the move is safe
; Calls GRID_ADDRESS
; This subroutine does not check if the input (R0) is
; valid. This functionality is implemented elsewhere.
;***********************************************************
SAFE_MOVE
ADD R6, R6, #-3 ; allocate space in stack for R7
STR R0, R6, #0 ; save R0 on stack
STR R3, R6, #1 ; save R3 on stack
STR R7, R6, #2 ; save R7 on stack
LEA R1, CURRENT_ROW ; load current row pointer
LDR R1, R1, #0 ; load row
LEA R2, CURRENT_COL ; load current column pointer
LDR R2, R2, #0 ; load column
LD R3, ASCII_I_COMPLEMENT ; load the 2's complement of ASCII 'i'
ADD R3, R0, R3 ; compare the character with 'i'
BRz MOVU
ADD R3, R3, #-1 ; compare the character with 'j'
BRz MOVL
ADD R3, R3, #-1 ; compare the character with 'k'
BRz MOVD
MOVR
ADD R2, R2, #1 ; x++
BR CHKSAFE
MOVL
ADD R2, R2, #-1 ; x--
BR CHKSAFE
MOVU
ADD R1, R1, #-1 ; y--
BR CHKSAFE
MOVD
ADD R1, R1, #1 ; y++
CHKSAFE
ADD R1, R1, #0 ; y<0 -> unsafe
BRn UNSAFE
ADD R0, R1, #-7 ; y>7 -> unsafe
BRp UNSAFE
ADD R2, R2, #0 ; x<0 -> unsafe
BRn UNSAFE
ADD R0, R2, #-7 ; x>7 -> unsafe
BRp UNSAFE
JSR GRID_ADDRESS ; get address of new position
LDR R0, R0, #0 ; load character at position
LD R3, HYENA_COMPLEMENT ; load complement of hyena character
ADD R0, R0, R3 ; compare char with hyena
BRnp RETN ; if not hyena -> safe
UNSAFE
AND R1, R1, #0 ; return -1
NOT R1, R1
RETN
LDR R0, R6, #0 ; load R0
LDR R3, R6, #1 ; load R3
LDR R7, R6, #2 ; load R7
ADD R6, R6, #3 ; restore stack pointer
JMP R7
HYENA_COMPLEMENT .FILL x-23
;***********************************************************
; APPLY_MOVE
; This subroutine makes the move if it can be completed.
; It checks to see if the movement is safe by calling
; SAFE_MOVE which returns the coordinates of where the move
; goes (or -1 if movement is unsafe as detailed below).
; If the move is Safe then this routine moves the player
; symbol to the new coordinates and clears any walls (|�s and -�s)
; as necessary for the movement to take place.
; If the movement is unsafe, output a console message of your
; choice and return.
; Input:
; R0 has move (i or j or k or l)
; Output: None; However must update the GRID and
; change CURRENT_ROW and CURRENT_COL
; if move can be successfully applied.
; Notes: Calls SAFE_MOVE and GRID_ADDRESS
;***********************************************************
APPLY_MOVE
ADD R6, R6, #-7 ; allocate space in stack for R7
STR R0, R6, #0 ; save R0 on stack
STR R1, R6, #1 ; save R1 on stack
STR R2, R6, #2 ; save R2 on stack
STR R3, R6, #3 ; save R3 on stack
STR R4, R6, #4 ; save R4 on stack
STR R5, R6, #5 ; save R5 on stack
STR R7, R6, #6 ; save R7 on stack
LD R3, CROW ; load current row pointer
LDR R3, R3, #0 ; load current position
LEA R5, OLDR
STR R3, R5, #0 ; save in oldr
LD R4, CCOL ; load current col pointer
LDR R4, R4, #0 ; load current position
LEA R5, OLDC
STR R4, R5, #0 ; save in oldc
JSR SAFE_MOVE ; check if it's a safe move
ADD R1, R1, #0 ; see if it's safe
BRn NOMOVE ; if negative, don't move
JSR GRID_ADDRESS ; get address of next move
LD R5, ASTER
STR R5, R0, #0 ; save asterisk
LD R3, CROW ; load current row pointer
STR R1, R3, #0 ; save row
LD R4, CCOL ; load current col pointer
STR R2, R4, #0 ; save column
LD R1, OLDR ; get old position
LD R2, OLDC ; get old position
JSR GRID_ADDRESS ; get address of previous position
LD R5, SPACE
STR R5, R0, #0 ; save space
LDR R3, R3, #0 ; load current row position
LDR R4, R4, #0 ; load current col position
LD R5, ROWWID ; load rowwidth
NOT R0, R1
ADD R0, R0, #1
ADD R0, R3, R0 ; subtract cur row - old row
BRp TSTCOL ; if positive, use rowwid
BRz ADD0 ; if zero, use zero
NOT R5, R5 ; use -rowwid
ADD R5, R5, #1
BR TSTCOL
ADD0
AND R5, R5, #0
TSTCOL
NOT R0, R2
ADD R0, R0, #1
ADD R4, R4, R0 ; subtract cur col - old col
ADD R4, R4, R5 ; add change in row + change in col
JSR GRID_ADDRESS ; get address of position
ADD R0, R0, R4 ; advance grid position
LD R5, SPACE
STR R5, R0, #0 ; save space
BR APPRTN
NOMOVE
LEA R0, UNSAFE_MOVE_STRING ; if the input was unsafe, output corresponding
TRAP x22 ; message and go back to prompt
APPRTN
LDR R0, R6, #0 ; load R0
LDR R1, R6, #1 ; load R1
LDR R2, R6, #2 ; load R2
LDR R3, R6, #3 ; load R3
LDR R4, R6, #4 ; load R4
LDR R5, R6, #5 ; load R5
LDR R7, R6, #6 ; load R7
ADD R6, R6, #7 ; restore stack pointer
JMP R7
CROW .FILL CURRENT_ROW
CCOL .FILL CURRENT_COL
HROW .FILL HOME_ROW
HCOL .FILL HOME_COL
OLDR .BLKW 1
OLDC .BLKW 1
UNSAFE_MOVE_STRING .STRINGZ "\nUnSafe Move\n"
;***********************************************************
; IS_SIMBA_HOME
; Checks to see if the Simba has reached Home.
; Input: None
; Output: R2 is zero if Simba is Home; -1 otherwise
;
;***********************************************************
IS_SIMBA_HOME
ADD R6, R6, #-3 ; allocate space in stack for registers
STR R1, R6, #0 ; save R1 on stack
STR R3, R6, #1 ; save R3 on stack
STR R4, R6, #2 ; save R4 on stack
LD R1, CROW ; load current row pointer
LDR R1, R1, #0 ; load row
LD R2, CCOL ; load current column pointer
LDR R2, R2, #0 ; load column
LD R3, HROW ; load home row pointer
LDR R3, R3, #0 ; load row
LD R4, HCOL ; load home column pointer
LDR R4, R4, #0 ; load column
NOT R3, R3 ; convert home row to negative
ADD R3, R3, #1
NOT R4, R4 ; convert home col to negative
ADD R4, R4, #1
ADD R1, R1, R3 ; compare rows and columns
BRnp NOHOME ; if not equal, not home
ADD R2, R2, R4
BRz ISHOME ; if zero, it's home
NOHOME
AND R2, R2, #0 ; else, return -1
NOT R2, R2
ISHOME
LDR R1, R6, #0 ; load R1
LDR R3, R6, #1 ; load R3
LDR R4, R6, #2 ; load R4
ADD R6, R6, #3 ; restore stack pointer
JMP R7
.END
; This section has the linked list for the
; Jungle's layout: #(0,1)->H(4,7)->I(2,1)->#(1,1)->#(6,3)->#(3,5)->#(4,4)->#(5,6)
.ORIG x5000
.FILL Head ; Holds the address of the first record in the linked-list (Head)
blk2
.FILL blk4
.FILL #1
.FILL #1
.FILL x23
Head
.FILL blk1
.FILL #0
.FILL #1
.FILL x23
blk1
.FILL blk3
.FILL #4
.FILL #7
.FILL x48
blk3
.FILL blk2
.FILL #2
.FILL #1
.FILL x49
blk4
.FILL blk5
.FILL #6
.FILL #3
.FILL x23
blk7
.FILL #0
.FILL #5
.FILL #6
.FILL x23
blk6
.FILL blk7
.FILL #4
.FILL #4
.FILL x23
blk5
.FILL blk6
.FILL #3
.FILL #5
.FILL x23
.END