Right, while I'm on the subject, I thought I'd make a quick point about abstraction as well. It may be more advanced for a simple first exercise, so you might want to skip reading it and come back later when we've done more assignments

.
So, say we want to control 10 bouncy balls like this. How would we do it with the code we have so far? Well, one solution would be to copy/paste the code 10 times and change labels, and it would work. But... what about if we found a bug? We'd then have to change it to 10 points in the code! And then maybe we'll need a change later on. 10 changes again! Etc, etc. Soon it becomes ultra tedious to say the least!
What could we do then? Well...
the_balls:
rept 10
dc.l 160 ; ball x position
dc.l 120 ; ball y position
dc.l 1 ; vertical direction of ball
dc.l 1 ; horizontal direction of ball
endr
topborder dc.l 0 ; sets top border
bottomborder dc.l 240 ; sets bottom border
leftborder dc.l 0 ; sets left border
rightborder dc.l 320 ; sets right border
mainloop
move.l #the_balls,a0
bsr.s bouncy
bra.s mainloop
bouncy:
movem.l (a0),d0-d3 ;load ball_x in d0, ball_y in d1, x_direction in d2 and y_direction in d3
sub.l d2,d0 ; moves ball left by one pixel
add.l d3,d1 ; moves ball down by one pixel
moveball:
move.l d0,ball_x ; updates ball_x variable
move.l d1,ball_y ; updates ball_y variable
cmp.l leftborder,d0 ; compares left border to x position
bne.s .check_right ; branches if not equal to left border
moveq #1,d2 ; then starts moving the ball right
bra.s .check_top ; now go check for top/bottom
.check_right:
cmp.l rightborder,d0 ; compares right border to x position
bne.s .check_top ; branches if not equal to right border
moveq #-1,d2 ; then starts moving the ball left
.check_top:
cmp.l topborder,d1 ; compares top border to y position
bne.s .check_bottom ; branches if not equal to top border
moveq #1,d3 ; then moves the ball down
bra.s .check_done
.check_bottom:
cmp.l bottomborder,d1 ; compares bottom border to y position
beq.s .move_up ; branches if equal to bottom border
moveq #-1,d3 ; then moves the ball up
.check_done:
movem.l d0-d3,(a0)
rts ;all done, thank you, drive thru!
Eh what?
Firstly, I've defined 10 balls. They're set up at the top.
rept and
endr define a block to be repeated as many times as we want. Saves some typing

. As a consequence, each ball's values are directly after the previous one. So what, you'll ask. We still have to reference them somehow, right?
What I basically did there was to use pointers. Registers a0 to a7, as we all know, are called address registers. In addition to just holding numbers, they have some extra functionality. For example, if an address register holds a valid address, then we can access the memory in that address by the use of parentheses. So, if a0 is loaded with the value $10000, then executing
move.l (a0),d0
will fetch the longword that a0 points to and load it in a0. Cool huh?

Of course there are limits to what one can do, but most of the 68000 instruction set is very flexible and we can use pointer logic in lots of places.
So, how does this help in our case? Simple. To control the first ball, I just load the address of the first element of the first ball, its ball_x to be precise, to a0. I then call the subroutine
bouncy. Assuming that a0 contains the address of the ball's structure we want to check, I just go ahead and read all variables with the movem, but instead of a fixed address I use the one stored in a0!
movem.l (a0),d0-d3 ;load ball_x in d0, ball_y in d1, x_direction in d2 and y_direction in d3
After all processing is done, I simply write it back to the address of a0:
movem.l d0-d3,(a0)
So, can you guess how to process the 2nd bacll? Quite simply, we can load the address of the 2nd ball's structure. We can calculate that quite easily; since each ball uses 4 longwords to store its data, the 2nd ball is located at 4bytes*4longwords=16 bytes after the first one. So,
move.l #the_balls+4*4,a0
will point to our 2nd ball! (yes, arithmetic expressions are allowed as long as they're not too complex)
And that's it really, as you see turning an ordinary routine to a more generic one isn't as difficult as you might first think