Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Programming game in assembly language I need help programming a game in assembly

ID: 3772595 • Letter: P

Question

Programming game in assembly language

I need help programming a game in assembly language. I have most of the program ready to go, just need help with where to start on the code.

B - is a block, your character can not go through them

G - is gold, your character can pick them up for points

* - is the wall, your character can not go through the walls.

Your program should, at a minimum, do the following:

Stop your character from going out of bounds - don’t let them go past an asterisks (*)

Stop the character from going through a block (B)

When the character goes over a G, give them points

Display the player's score and keep it updated

Add an exit to the map - place an E that terminates the program when they go over it

%include "asm_io.inc"
%include "io.inc"
; initialized data is put in the .data segment
segment .data
clear db 27,"[2J",27,"[1;1H",0
cc db 27,"c",0
scanFormat db "%c",0
file db "input.txt",0
mode db "r",0
formatA db "%c",0
x dd 3
y dd 3
prevX dd 0
prevY dd 0

rows dd 8
cols dd 27
; uninitialized data is put in the .bss segment
segment .bss
text resb 2000

; code is put in the .text segment
segment .text
global asm_main
   extern fscanf
   extern fopen
   extern fclose
   extern scanf
   extern getchar
   extern putchar
asm_main:
enter 0,0 ; setup routine
pusha
   ;***************CODE STARTS HERE*******
       mov eax, clear ;two lines to clear
       call print_string ;clear the screen
       mov eax, cc
       call load   ;load the file into text
       call update ;update the file with the location
       mov eax, text
       call print_string

       mov ecx, 20
   top:
       call movement
       call update
       mov eax, clear ;two lines to clear
       call print_string ;clear the screen
       mov eax, text
       call print_string
       loop top

   ;***************CODE ENDS HERE*********
popa
mov eax, 0 ; return back to C
leave   
ret
;*********************************
;* Function to load var text with*
;* input from input.txt *
;*********************************
load:
   push eax
   push esi

   sub esp, 20h
   ;get the file pointer
   mov dword [esp+4], mode; the mode for the file which is "r"  
   mov dword [esp], file; the name of the file. Hard coded here (input.txt)
   call fopen ; call fopen to open the file

   ;read stuff
   mov [esp], eax; mov the file pointer to param 1
   mov eax, esp ;use stack to store a pointer where char goes
   add eax, 1Ch ;address is 1C up from the bottom of the stack
   mov [esp+8], eax;pointer is param 3
   mov dword [esp+4], scanFormat; fromat is param 2

   mov edx, 0
   mov [prevX], edx
   mov [prevY], edx

scan:   call fscanf; call scanf
   cmp eax, 0 ; eax will be less than 1 when EOF
   jl done; eof means quit
   mov eax, [esp+1Ch]; mov the result (on the stack) to eax
  
   cmp al, 'M'
   jz Mario
  
   mov edx, [prevX]; increment prevX
   inc edx
   mov [prevX], edx

   cmp al, 10
   jz NewLine
  
   jmp save
NewLine:

   mov dword [prevX], 0
   mov edx, [prevY]
   inc edx
   mov [prevY], edx
   jmp save
  
Mario:
   mov edx, [prevX]
   mov [x], edx
   mov edx, [prevY]
   mov [y], edx
   jmp save
  
save:
  
   mov [text + esi], al; store in the array
   inc esi; add one to esi (index in the array)
   cmp esi, 2000; dont go tooo far into the array
   jz done; quit if went too far
   jmp scan ;loop back
done:
   call fclose; close the file pointer
   mov byte [text+esi],0 ;set the last char to null
   add esp, 20h; unallocate stack space
  
   pop esi   ;restore registers
   pop eax
   ret

   ;*********************************
   ;* Function to update the screen *
   ;* *
   ;*********************************

update:
   push eax
   push ebx
   ;update the new loc
   mov eax, [x]
   mov ebx, [y]
   mov edx, 0
   imul ebx, [cols]

   add eax, ebx
   mov byte [text + eax], 'M'
   ;update the old loc
   mov eax, [prevX]
   mov ebx, [prevY]
   mov edx, 0
   imul ebx, [cols]

   add eax, ebx
   mov byte [text + eax], ' '
  
   pop ebx
   pop eax
  
ret


;*********************************
;* Function to get mouse movement*
;* *
;*********************************
movement:  
   pushad
mov ebx, [x]
   mov [prevX], ebx;save old value of x in prevX
mov ebx, [y]
   mov [prevY], ebx; save old value of y in prevY
   call canonical_off
   call echo_off
   mov eax, formatA
   push eax
   ;http://stackoverflow.com/questions/15306463/getchar-returns-the-same-value-27-for-up-and-down-arrow-keys
   call getchar
   call getchar
   call getchar
   call canonical_on
   call echo_on
   cmp eax, 43h; right
   jz right
   cmp eax, 44h; left
   jz left
   cmp eax, 42h; right
   jz up
   cmp eax, 41h; left
   jz down
   jmp over
right:
mov eax, [x]
inc eax
   mov [x], eax
   jmp mDone
left:
    mov eax, [x]
   dec eax
   mov [x], eax
jmp mDone
up:
   mov eax, [y]
   add eax, 1
   mov [y], eax
   jmp mDone
down:
    mov eax, [y]
   sub eax, 1
   mov [y], eax
   jmp mDone
mDone:
over:pop eax
   popad
   ret

segment .data
termios: times 36 db 0
stdin: equ 0
ICANON: equ 1<<1
ECHO: equ 1<<3


segment .text
global canonical_off, echo_off,echo_on, canonical_on, write_stdin_termios, read_stdin_termios
;*********************************
;* Function turn off canonical *
;* *
;*********************************
canonical_off:
call read_stdin_termios
; clear canonical bit in local mode flags
push eax
mov eax, ICANON
not eax
and [termios+12], eax
pop eax
call write_stdin_termios
ret

;*********************************
;* Function turn off echo *
;* *
;*********************************
echo_off:
call read_stdin_termios
; clear echo bit in local mode flags
push eax
mov eax, ECHO
not eax
and [termios+12], eax
pop eax
call write_stdin_termios
ret

;*********************************
;* Function turn canonical on *
;* *
;*********************************
canonical_on:
call read_stdin_termios
; set canonical bit in local mode flags
or dword [termios+12], ICANON
call write_stdin_termios
ret

;*********************************
;* Function turn echo on *
;* *
;*********************************
echo_on:
call read_stdin_termios
; set echo bit in local mode flags
or dword [termios+12], ECHO
call write_stdin_termios
ret

;*********************************
;* Function read termios *
;* *
;*********************************
read_stdin_termios:
push eax
push ebx
push ecx
push edx

mov eax, 36h
mov ebx, stdin
mov ecx, 5401h
mov edx, termios
int 80h

pop edx
pop ecx
pop ebx
pop eax
ret
;*********************************
;* Function write a termios *
;* *
;*********************************
write_stdin_termios:
push eax
push ebx
push ecx
push edx

mov eax, 36h
mov ebx, stdin
mov ecx, 5402h
mov edx, termios
int 80h

pop edx
pop ecx
pop ebx
pop eax
ret

Explanation / Answer

%include "asm_io.inc"
%include "io.inc"
; initialized data is put in the .data segment
segment .data
clear db 27,"[2J",27,"[1;1H",0
cc db 27,"c",0
scanFormat db "%c",0
file db "input.txt",0
mode db "r",0
formatA db "%c",0
x dd 3
y dd 3
prevX dd 0
prevY dd 0
holdprevX dd 0
holdprevY dd 0
rows dd 15
cols dd 51
scorestring db "Your score is: ", 0
score dd 20
mario dd "m", 0

; uninitialized data is put in the .bss segment
segment .bss
text resb 2000
;score resb 1

; code is put in the .text segment
segment .text
    global asm_main
    extern fscanf
    extern fopen
    extern fclose
    extern scanf
    extern getchar
    extern putchar
asm_main:
    enter   0,0               ; setup routine
    pusha
    ;***************CODE STARTS HERE*******
        mov eax, clear    ;two lines to clear
        call print_string ;clear the screen
        mov eax, cc
        call load   ;load the file into text
        call update ;update the file with the location
        mov eax, scorestring
        call print_string
        mov eax, [score]
        call print_int
        call print_nl
        mov eax, text
        call print_string

        mov ecx, 200
      top:
        mov eax, 1 ;update score
        sub [score], eax

        call movement
        call update

        mov eax, clear    ;two lines to clear
        call print_string ;clear the screen

        mov eax, scorestring ;print score and text string
        call print_string
        mov eax, [score]
        call print_int
        call print_nl
        mov eax, text
        call print_string

        mov ebx, [x] ;check to see if we need to exit
        mov ecx, [y]
        inc ecx
        imul ecx, [cols]
        add ecx, ebx
        mov eax, [text+ecx]
        cmp al, 'E'
        jz exit

        loop top
       exit:
    ;***************CODE ENDS HERE*********
    popa
    mov     eax, 0            ; return back to C
    leave
    ret


;*********************************
;* Function to load var text with*
;* input from input.txt          *
;*********************************
load:
    push eax
    push esi

    sub esp, 20h
    ;get the file pointer
    mov dword [esp+4], mode; the mode for the file which is "r"
    mov dword [esp], file; the name of the file. Hard coded here (input.txt)
    call fopen ; call fopen to open the file

    ;read stuff
    mov [esp], eax; mov the file pointer to param 1
    mov eax, esp ;use stack to store a pointer where char goes
    add eax, 1Ch ;address is 1C up from the bottom of the stack
    mov [esp+8], eax;pointer is param 3
    mov dword [esp+4], scanFormat; fromat is param 2

    mov edx, 0
    mov [prevX], edx
    mov [prevY], edx

scan:
    call fscanf; call scanf
    cmp eax, 0 ; eax will be less than 1 when EOF
    jl done; eof means quit
    mov eax, [esp+1Ch]; mov the result (on the stack) to eax

    cmp al, 'm'
    jz Mario

    mov edx, [prevX]; increment prevX
    inc edx
    mov [prevX], edx

    cmp al, 10
    jz NewLine

    jmp save
NewLine:
    mov dword [prevX], 0
    mov edx, [prevY]
    inc edx
    mov [prevY], edx
    jmp save
Mario:
    mov edx, [prevX]
    mov [x], edx
    mov edx, [prevY]
    mov [y], edx
    jmp save
save:
    mov [text + esi], al; store in the array
    inc esi; add one to esi (index in the array)
    cmp esi, 2000; dont go tooo far into the array
    jz done; quit if went too far
    jmp scan ;loop back
done:
    call fclose; close the file pointer
    mov byte [text+esi],0 ;set the last char to null
    add esp, 20h; unallocate stack space

    pop esi ;restore registers
    pop eax
    ret


;*********************************
;* Function to update the screen *
;*                               *
;*********************************
update:
    push eax
    push ebx

    ;update the new loc
    mov eax, [x]
    mov ebx, [y]
    imul ebx, [cols]
    add eax, ebx
    mov ebx, [mario]
    cmp bl, 'm'
    jz littlem
    jmp bigm
littlem:
    mov byte [text + eax], 'm'
    jmp done2
bigm:
    mov byte [text+eax], 'M'
done2:
    ;update the old loc
    mov eax, [prevX]
    mov ebx, [prevY]
    mov edx, 0
    imul ebx, [cols]
    add eax, ebx
    mov byte [text + eax], ' '

    pop ebx
    pop eax
    ret


;*********************************
;* Function to get mouse movement*
;*                               *
;*********************************
movement:
    pushad
    mov ebx, [prevX]     ;need to store prevX and prevY for when we call checkMove
    mov [holdprevX], ebx ;and we are not able to move
    mov ebx, [prevY]
    mov [holdprevY], ebx
        mov ebx, [x]
    mov [prevX], ebx;save old value of x in prevX
        mov ebx, [y]
    mov [prevY], ebx; save old value of y in prevY
    call canonical_off
    call echo_off
    mov eax, formatA
    push eax
    ;http://stackoverflow.com/questions/15306463/getchar-returns-
    ;the-same-value-27-for-up-and-down-arrow-keys
    call getchar
    call getchar
    call getchar
    call canonical_on
    call echo_on

    push eax ;push the arrowkey to use in checkMove
    cmp eax, 43h; right
    jz right
    cmp eax, 44h; left
    jz left
    cmp eax, 42h; down
    jz down
    cmp eax, 41h; up
    jz up
    ;jmp mDone
right:
    call checkMove
    cmp edi, 0
    jz undo
    call fall ;
        mov eax, [x]
        inc eax
    mov [x], eax
    jmp mDone
left:
    call checkMove
    cmp edi, 0
    jz undo
    call fall
    mov eax, [x]
    dec eax
    mov [x], eax
        jmp mDone
down:
    call checkMove
    cmp edi, 0
    jz undo
    call fall
    jmp mDone
up:
    mov ebx, [x]
    mov ecx, [y]
    inc ecx
    imul ecx, [cols]
    add ebx, ecx
    mov ebx, [text+ebx]
    cmp bl, ' '
    jz undo
    call checkMove
    cmp edi, 0
    jz undo
    jmp mDone
undo: ;if we cant mov then we need to reset prevX and prevY
    mov eax, [holdprevX]
    mov [prevX], eax
    mov eax, [holdprevY]
    mov [prevY], eax
mDone:

    add esp, 4
    pop eax
    popad
    ret


;*********************************
;* Function to check if there is *
;* a block in the way            *
;*********************************
checkMove:
    push ebp
    mov ebp, esp
    push eax
    push ebx
    push ecx
    push edx

    mov ebx, [x] ;mov x and y into registers here so we don't have to do it each time
    mov ecx, [y] ;in the different if statements

    mov eax, [ebp+8] ;parameter holding which input was givin in the movement function
    cmp eax, 43h; right
    jz checkright
    cmp eax, 44h; left
    jz checkleft
    cmp eax, 42h; down
    jz checkdown
    cmp eax, 41h; up
    jz checkup
    ;jmp checkDone
checkright:
    imul ecx, [cols]
    add ebx, ecx
    add ebx, 1
    mov eax, [text+ebx]
    ;mov ecx, [x]
    ;mov edx, [y]
    ;mov esi, [cols]
    ;dump_regs 1
    push ebx
    push eax
    call gold
    cmp al, 'B'
    jz noright
    cmp al, '*'
    jz noright
    cmp al, 'E'
    jz noright
    cmp al, '?'
    jz noright
    jmp yesright
    noright:
    mov edi, 0
    jmp checkDone
    yesright:
        mov edi, 1
    jmp checkDone
checkleft:
    imul ecx, [cols]
    add ebx, ecx
    sub ebx, 1
    mov eax, [text+ebx]
        ;mov ecx, [x]
        ;mov edx, [y]
        ;mov esi, [cols]
        ;dump_regs 1
    push ebx
    push eax
    call gold
    cmp al, 'B'
    jz noleft
    cmp al, '*'
    jz noleft
    cmp al, 'E'
    jz noleft
    cmp al, '?'
    jz noleft
    jmp yesleft
    noleft:
    mov edi, 0
    jmp checkDone
    yesleft:
        mov edi, 1
    jmp checkDone
checkdown:
    inc ecx
    imul ecx, [cols]
    add ebx, ecx
    mov eax, [text+ebx]
    cmp al, 'B'
    jz nodown
    cmp al, '*'
    jz nodown
    cmp al, 'E'
    jz nodown
    cmp al, '?'
    jz nodown
    jmp yesdown
    nodown:
    mov edi, 0
    jmp checkDone
    yesdown:
        mov edi, 1
    jmp checkDone
checkup:
    mov edx, [y] ;need two registers with y for when we need to update y because
    dec edx      ;it gets overwritten in ecx when we multiply (used in statements below
    dec ecx
    imul ecx, [cols] ; <----- gets overwritten so we need it in edx as well
    add ebx, ecx
    mov eax, [text+ebx]
    push ebx
    push eax ;use the character & location we are checking as a parameter for gold function
    call gold ;check to see if the space is a G using the parameters
    cmp al, 'B'
    jz firstblocked
    cmp al, '*'
    jz firstblocked
    cmp al, '?'
    jz firstblocked
    mov ecx, [y]
    mov edx, [y]
    mov ebx, [x]
    sub ecx, 2
    sub edx, 2
    imul ecx, [cols]
    add ebx, ecx
    mov eax, [text+ebx]
    push ebx
    push eax
    call gold
    call flower
    cmp al, 'B'
    jz blocked
    cmp al, '*'
    jz blocked
    cmp al, '?'
    jz blocked
    mov ecx, [y]
    mov edx, [y]
    mov ebx, [x]
    sub ecx, 3
    sub edx, 3
    imul ecx, [cols]
    add ebx, ecx
    mov eax, [text+ebx]
    push ebx
    push eax
    call gold
    cmp al, 'B'
    jz blocked
    cmp al, '*'
    jz blocked
    cmp al, '?'
    jz blocked
    jmp notblocked
    firstblocked:
    inc edx
    mov [y], edx
    mov edi, 0
    jmp checkDone
    blocked:
    inc edx
    mov [y], edx
    mov edi, 1
    jmp checkDone
    notblocked:
    mov [y], edx
    mov edi, 1
    jmp checkDone
    jmp checkDone
checkDone:

    pop edx
    pop ecx
    pop ebx
    pop eax
    mov esp, ebp
    pop ebp
    ret

;*********************************
;* Function to calculate where   *
;* you will fall to              *
;*********************************
fall:
    push ebp
    mov ebp, esp
    push eax
    push ebx
    push ecx

    mov eax, [x]
    mov ebx, [ebp+8]
    cmp ebx, 43h; right
    jz fallRight
    cmp ebx, 44h; left
    jz fallLeft
    cmp ebx, 42h; down
    jz fallDone
fallRight:
    add eax, 1
    jmp fallDone
fallLeft:
    sub eax, 1
fallDone:
    mov ebx, [y]
    imul ebx, [cols]
    add ebx, eax
    mov ecx, [y]
    while:
    cmp bl, '*'
    jz endwhile
    cmp bl, 'B'
    jz endwhile
    cmp bl, 'E'
    jz endwhile
    cmp bl, '?'
    jz endwhile
    inc ecx
    mov ebx, ecx
    imul ebx, [cols]
    add ebx, eax
    push ebx
    mov ebx, [text+ebx]
    push ebx
    call gold
    jmp while
    endwhile:
    dec ecx
    mov [y], ecx


    pop ecx
    pop ebx
    pop eax
    mov esp, ebp
    pop ebp
    ret


;*********************************
;* Function to add 100 points    *
;* when you hit a G. Also makes *
;* Mario a capital M if it finds *
;* a F.                          *
;*********************************
gold:
    push ebp
    mov ebp, esp
    push eax
    push ebx

    mov eax, [ebp+8]
    mov ebx, [ebp+12]

    cmp al, 'G'
    jz add100
    cmp al, 'F'
    jz yesflower
    jmp nogold
add100:
    mov eax, 100
    add [score], eax
    mov byte [text+ebx], ' '
    jmp nogold
yesflower:
    mov eax, 50
    add [score], eax
    mov byte [mario], 'M'
nogold:
    pop ebx
    pop eax
    mov esp, ebp
    pop ebp
    ret


;*********************************
;* Function to add a flower to   *
;* the map                       *
;*********************************
flower:
        push ebp
        mov ebp, esp
    push eax

        mov eax, [ebp+8]
        cmp al, '?'
    jz yes?
    jmp no?
yes?:
    mov eax, [ebp+12]
    sub eax, 51 ;sub 51 because thats how many characters in a row and we need one row up
    mov byte [text+eax], 'F' no?:

    pop eax
    mov esp, ebp
    pop ebp
    ret