Go4Expert (http://www.go4expert.com/)
-   Assembly Language Programming (ALP) Forum (http://www.go4expert.com/forums/assembly-language-programming-forum/)
-   -   Having subroutine trouble - 6800 assembly (http://www.go4expert.com/forums/subroutine-trouble-6800-assembly-t4368/)

Qik 19May2007 18:28

Having subroutine trouble - 6800 assembly
Hi guys, i'm new to the forums but i saw some other articles and the advice given is pretty solid, so i thought i'd come here in my desperate hour of need.

The object is to design part of a numbers game (it's for uni, i've been working for about 2 days solid on this and i'm still not getting it)

i've got the clearing of the screen, and the basic structure along with some array usage down, but my subroutines keep pointing back to the start of my program and not to where the subroutine was called from.

The idea is to have the program in a permenant loop that does the following:
1. moves numbers down 1 row on the screen
2. decides if it needs to indroduce another number based on a randomised (with limits)countdown timer and adds it into the array accordingly (the value and column position is also random)
3. when a number reaches the bottom (row position 20) it moves it back to position 1.

Here's the code i've got so far, i swear i've redone this like 4 or 5 times (the first attempt was so dismal i decided it best to just delete it and start afresh)

All the comments that say 'should be 54' and whatnot i've reduced to 2 for the purposes of stepping through the program.


numcols .equ 54
numrows .equ 20
        ldx enemyval
        ldab #2; should be 54
resetenemies        ldaa #0
        staa enemyrow,x
        bne resetenemies
        ldab #2; should be 54
resetenemyval ldaa #0
        staa enemyval,x
        bne resetenemyval
        ldaa #2
        jsr randomnumber
        ldab randno; then multiply X 2
        staa countdown
engineloop jsr clearscreen; the game engine loop
        ldaa #54
        staa updatecount; loads 54 colums for the update subroutine
        jsr updateenemies
braland        ldaa #2
        jsr checknewenemy
        bne engineloop
clearscreen ldaa #1
clrscrn        ldx        #screen       
                stx  pcaret        ;reset caret
                ldaa #$41
                staa 0,x
                staa 54,x
                staa 2,x
                staa 3,x
csnlp1        clr 0,x                ;[x] = 0
                inx                        ;x++
                cpx        $FEE8        ;screen+1000
                bne        csnlp1        ;loop
                bra        braland                ;return
updateenemies        ldx #enemyval
        ldaa enemyval,x
        staa a
        ldx #enemyrow
        ldab enemyrow,x
        stab y
        bgt removing
removing ldx #screen
        ldaa #$30
        staa y,x ; writes blank to position of old number
        ldaa y
        inca ; adds 1 to the current row, giving the next row
        staa y
        ldaa #a ; loads the enemyvalue
        staa y,x; writes enemyvalue onto the correct screen position
        ldaa y
        cmpa #19
        bgt movenumberup ; if y > 19, move it to the top row again ready for the next redraw
        jmp endif
movenumberup ldaa #0
        staa enemyrow,x; sets the row position that was 20 back to 0 (the top row)
endif        inx
        ldaa updatecount; loads the counter which is 54
        staa updatecount
        bne updateenemies; loops back to the top
checknewenemy        ldaa countdown
        staa countdown
        bne addnewenemy; if countdown is 0, then go to the addnewenemies function
addnewenemy jsr randomnumber
        ldaa randno; after this, divide random by 4
        staa i
        staa countdown; divide by 4 here
        ldaa i
        staa enemyval,x; stores the enemyvalue i at position i in enemyval
        staa enemyrow,x; stores the new enemy position at row 1, position i in enemyrow
        ldaa randno; then make randno between 1-54
randomnumber ldaa #7
        staa randno


a .byte 0; current value for redrawing enemyval
y .byte 0; current value for redrawing enemyrow       
i .byte 0; variable for random numbers put into enemyrow and enemyval
scrhigh .byte $FB        ; high byte screen address
scrlow        .byte $00        ; low byte screen address
rowcount .byte 20        ; number of rows to count
countdown .byte 5 ;time till next enemy
enemyval .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;array of enemy values
enemyrow .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;array holding enemy row location
randno .byte 0
count .byte 0
randcount .byte 0
updatecount .byte 0
screen        .equ $FB00
pcaret        .stw $FB00

The main problem i have is the subroutines not going to where they should be,

I'm not here for a free homework solution, i genuinely want to learn this stuff to improve my (currently underdeveloped) skills as a programmer, i've programmed before in c++ java and also zscript (pseudocode for an online mud) but assembly is totally foreign to me. Any help would be greatly appreciated, I'll be checking in over the next day or so.

This is all being done on an emulator with a fixed size of 54X20 chars. Apologies for the messiness of the code, it's still a jumble while i work out what i'm doing.

Thanks in advance for any help.

DaWei 19May2007 21:05

Re: Having subroutine trouble - 6800 assembly
I'll propose something, but I won't actually read your code. It's far too ugly. Separate code items such as subroutines don't stand out enough to see them without a lot of searching. You also didn't place it in code tags to preserve any formatting you might have had. See the "Before you make a query" thread.

If a subroutine call is actually going to the subroutine, but not returning to the point of the call, then you have no doubt corrupted the return address. For most microprocessors, that would be because you've clobbered it on the stack.

shabbir 19May2007 22:08

Re: Having subroutine trouble - 6800 assembly
I have done the code formating and the url will help you do it next time.

DaWei 19May2007 23:05

Re: Having subroutine trouble - 6800 assembly
Realize also that if you wanted to use 2 instead of 54, you could just change one spot, numcols equ 54, to numcols equ 2. That's a big part of the purpose of using equ. Your code still doesn't make a lot of sense. Maybe it's not all shown. When you call a subroutine, the subroutine needs to end with a return statement. Any parameters passed to the subroutine need to be removed. The return value, if any, needs to be dealt with.

Your description of the problem is pretty good, but there are a number of issues that I don't see you addressing. How do you expect to get a number back from randno? You aren't sending one back. Is randno a library function, or have you implemented it somewhere.

Have you programmed in a higher level language, or is assembler your first step? Have you studied the basic working of microprocessors? It's difficult to address an issue if one doesn't know whether to look for improper syntax or improper understanding of the process.

Qik 20May2007 06:20

Re: Having subroutine trouble - 6800 assembly
I have done programming in java and a little in c++ as well as a huge amount in zscript/pseudocode. Part of the course is learning how processors work but i'm lacking some understanding in certain parts.

The code still has a number of issues, but the main thing right now is the subroutine not working properly. I'll fix up the code some more in the next couple of hours and post it back up in a more legible format.

One question though, would i be better off use BRA instead of subroutines? I haven't really used the stack much in the code itself but i don't quite get how it works in terms of getting the RTS back to where it should be.

Qik 20May2007 06:23

Re: Having subroutine trouble - 6800 assembly
also, am i using the ldx and indexing for arrays properly?

DaWei 20May2007 07:51

Re: Having subroutine trouble - 6800 assembly
One uses a subroutine because it's reusable. Call if from anywhere, it picks up from the point of call. When the call instruction is executed, the FOLLOWING instruction is put onto the stack and the ip is set to the address of the subroutine. When the subroutine hits the return, the address on the stack is popped into the ip, and off you go, right where you left off. The thing is, you can't screw up the stack. You can use it in the subroutine, but you have to clean it up before the return. Else, you'll pop some data or register contents of something that you've saved on the stack, and the processor will think that junk is the address to return to.

A branch or jump is merely selecting a new path for the execution to follow. A subroutine is a timeout to do something, then pick up where you left off. You need to get that difference into your head.

Qik 20May2007 08:40

Re: Having subroutine trouble - 6800 assembly
thanks, that's a big help. I dont really need subroutines for this project, simple jumps and branches will do.

I think the main problem now is the index register. Basically i'm having the value enemyrow to be an array with 54 numbers in it (default being 1,0,0,0 etc until 54 numbers fill the array) 54 because there are 54 columns. The values will range from 0-19 (there are 20 rows) so in the first array position, a value of 3 would indicate that there is an 'enemy' in row 3 in column 1.

I think it's a syntax thing, but here is a small snippet of my index reference code.


    ldaa y
        inca ; adds 1 to the current row, making it point to the next row
        staa y
        ldx #enemyrow; loads enemyrow back into x to write for the next line
        staa enemyrow,x; writes the new enemyrow position

What i'm trying to do here is to load the value y into the accumulator (in this case it's 1)

Then it increments and stores it back into y, making y = 2.

What i think might be wrong is ldx #enemyrow. I'm assuming that loads it into the index register, and then staa enemyrow,x is storing the value in accumulator a (which is 2) into the first array posiion, in pseudocode it would be enemyrow[0].

Is this correct?
The second part is this statement

a .equ 2
y .equ 2
      ldx #screen
      ldaa a
      staa y,x

That's with #screen loaded into the index register. i'm wanting it to write the value of a into y + current screen value. Normally the comman is staa 1,x but can i sub my value y into where 1 usually is?

duynguyenvan 28Aug2007 14:18

Re: Having subroutine trouble - 6800 assembly
Could you pls help me answer this question:
- Please take a look at my small Assembly program that reads a tring from keyboard, then displays all the characters that are not uper-case letters in reverse order:

.model small
.stack 100
        tb1 db 'Pls enter a string, enter to finish $'
        tb2 db 10,13,'The characters that are not uper-case : $'
        xau db 80 dup(?)
Main proc
        mov ax,@data
        mov ds, ax
        mov es, ax
        mov ah,9
        lea dx,tb1
        int 21h
        xor cx,cx
        lea di,xau
nhap:        mov ah,1
        int 21h
        cmp al,13
        je thoi
        cmp al,'A'
        jb dung
        cmp al,'Z'
        ja dung
        jmp nhap
dung:        stosb
        inc cx
        jmp nhap
thoi:        mov ah,9
        lea dx,tb2
        int 21h
        dec di
        mov si,di
        mov ah,2
quay:        lodsb       
        mov dl,al
        int 21h
        loop quay
        mov ah,4ch
        int 21h
Main endp
        End main

The code above runs very well, even though i did not use the Clear Direction Flag (cld) instruction after the instruction in red (lea di,xau)
The string processing is still in forward direction.
The question is that: Why?

I appreciate your help.


shabbir 28Aug2007 15:28

Re: Having subroutine trouble - 6800 assembly
duynguyenvan you already have a thread - I need help !!!!!!!!!!!!!!!!!!!!!!!!!! for your query.

All times are GMT +5.5. The time now is 19:04.