Having subroutine trouble - 6800 assembly

Qik's Avatar, Join Date: May 2007
Newbie Member
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.

Last edited by shabbir; 19May2007 at 22:07.. Reason: Code block - http://www.go4expert.com/forums/misc.php?do=bbcode#code
DaWei's Avatar, Join Date: Dec 2006
Team Leader
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's Avatar, Join Date: Jul 2004
Go4Expert Founder
I have done the code formating and the url will help you do it next time.
DaWei's Avatar, Join Date: Dec 2006
Team Leader
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.

Last edited by DaWei; 19May2007 at 23:08..
Qik's Avatar, Join Date: May 2007
Newbie Member
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's Avatar, Join Date: May 2007
Newbie Member
also, am i using the ldx and indexing for arrays properly?
DaWei's Avatar, Join Date: Dec 2006
Team Leader
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's Avatar, Join Date: May 2007
Newbie Member
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's Avatar
Light Poster
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's Avatar, Join Date: Jul 2004
Go4Expert Founder
duynguyenvan you already have a thread - I need help !!!!!!!!!!!!!!!!!!!!!!!!!! for your query.