Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Comp: Smallest bouncing ball in 8086 assembly

322 views
Skip to first unread message

Stefan Wessels

unread,
May 28, 1993, 7:46:52 AM5/28/93
to
Hi,

One Sunday afternoon with nothing to do I set about writing a program in
8086 assembler that bounces a ball around the screen. I wanted to see how
small I could make it. I was surprised at how small I could actually get
it. I then gave this problem to our third year students who had just
completed a course in assembly programming.

The rules were basically:

1. The ball must bounce in a fashion similar to a given algorithm.
Basically:

Initialize x, y
x1=1
y1=1
Loop:
gotoxy (x,y)
print "0"
delay (1)
gotoxy (x,y)
print " "
x=x+x1
y=y+y1
if (x < 2) or (x > 79) x1 = -x1
if (y < 2) or (y > 24) y1 = -y1
goto Loop

2. The ball need not be the same character between iterations (hint: xor)
3. The screen contents (sp?) must not be destroyed by the ball.
4. The program must bounce the ball round at a speed that makes the path
clearly visable. (An empty delay of 65536 on my 486 is fine).
4. The program must terminate gracefully and return to DOS if the ESC
key is pressed.

My first attemptcame in at 56 bytes. The students were quite creative
and knocked several bytes off. One came in at 15 bytes. Using the mouse
cursor and bouncing the ball by hand. :-)

The idea is not to cheat on the rules, but to get a really small program ;)

Well, any takers? I'll give you some time to think, and then I'll post our
smallest programs.

Regards
Stefan

--------------------
swes...@cs.up.ac.za

Sean Captain Napalm Conner

unread,
May 28, 1993, 6:53:21 PM5/28/93
to
In article <swessels.5...@dos-lan.cs.up.ac.za> swes...@dos-lan.cs.up.ac.za (Stefan Wessels) writes:
>Hi,
>
>One Sunday afternoon with nothing to do I set about writing a program in
>8086 assembler that bounces a ball around the screen. I wanted to see how
>small I could make it. I was surprised at how small I could actually get
>it. I then gave this problem to our third year students who had just
>completed a course in assembly programming.
>
>My first attemptcame in at 56 bytes. The students were quite creative
>and knocked several bytes off. One came in at 15 bytes. Using the mouse
>cursor and bouncing the ball by hand. :-)
>
>The idea is not to cheat on the rules, but to get a really small program ;)
>
>Well, any takers? I'll give you some time to think, and then I'll post our
>smallest programs.
>

I guess you mean on a graphics screen, huh? What screen mode? CGA? VGA? EGA?
And 56 bytes ... that's pretty small ... I'm interested 8-)

-spc (Should be working, but ... 8-)


kug...@kuhub.cc.ukans.edu

unread,
May 29, 1993, 3:09:09 AM5/29/93
to
Hello all,

with interest I have read Stephan Wessels' challenging post and I have
given it a try, without beating Stephan by the way. But I thought,
perhaps someone could go further from here, and perhaps Stephan could
give some comments. I worked on this for about 3 hours now and I don't
see how it can be shrunk. But it is a nice competition.

I look forward to any other "solutions".

Regards,

Wimjan Jansen van de Laak
kug...@kuhub.cc.ukans.edu


"War doesn't decide who is right, just who is left." - unknown

--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------

; ball program - my try.

code segment para public 'Code'
assume cs:code, ds:code

org 100h
ProgStart:
xor dx,dx ; dx = x and y

AnotherTime:
mov ah,1h ; KeyPressed?
int 16h
jnz TheEnd ; yes -> TheEnd

GotoXY:
mov ah,02h ; x and y are in dx
int 10h

GetCurrChar:
mov ah,08h ; get char at current cursor location
int 10h

mov ah,0eh ; prepare ax for later
push ax ; and save it

PrintBallOrSo:
xor al,96 ; change the "ball"
int 10h ; and print it to the screen

DumLoop: ; some delay
loop DumLoop

GotoXYAgain:
mov ah,02h ; x and y still in dx
int 10h

PrintPrevChar:
pop ax ; restore prev char
int 10h

inc dl ; x = x + 1
RevXoffs equ $-1
jz ReverseX ; if x == 0 then reverse delta x

cmp dl,79 ; also if x is getting too big
jb TestY

ReverseX:
xor byte ptr [RevXoffs],8 ; switches between "dec dl", "inc dl"

TestY:
inc dh ; y = y + 1
RevYoffs equ $-1
jz ReverseY ; if y == 0 then reverse delta y

cmp dh,23 ; getting too big? then also reverse
jna ToTheStart

ReverseY:
xor byte ptr [RevYoffs], 8 ; switches between "dec dh", "inc dh"

ToTheStart:
jmp short AnotherTime

TheEnd:
ret

code ends
end ProgStart

--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------

Chris Hall

unread,
May 29, 1993, 9:12:30 PM5/29/93
to
This was the best I could get it down to; it's 49 bytes long.

width equ 80 ;width used; 160 bytes/line still assumed
height equ 25 ;height to use
ball equ 'O' ;character for the ball

main:
mov ah,0b8 ;al=0 **PROVIDED** no command-line params!
mov es,ax ;es=screen segment
xor di,di ;start at origin of screen
mov bl,162 ;offset to next position (bx=0 for .COM file)
mov dx,(width-1) by (height-1);no. of columns (dh)/rows (dl) left

l0:
mov al,ball ;ball character
xchg b es:[di],al ;store ball on screen, and get original byte
loop $ ;delay (cx=0 at start of .COM file)
stosb ;store original character back
lea di,[di+bx-1] ;di=di+bx-1=next screen position

dec dh ;column count
jz >l1 ;all columns done -- swap x
dec dl ;row count
jnz >l9 ;another row -- don't swap y yet

mov dl,height-1 ;dl=count
neg bx ;swap y-direction
jmp >l2 ;need this done, too

l1:
dec dx ;1 byte smaller than dec dl
mov dh,width-1 ;reset this
l2:
xor bl,60 ;swap x-direction

l9: ;jump to here to check key then repeat
mov ah,1 ;check keyboard buffer non-destructively
int 016
jz l0 ;no key, so repeat
ret ;come here when done -- 0 is already on stack.

Morten Welinder

unread,
May 31, 1993, 7:00:28 AM5/31/93
to
cah...@nyx.cs.du.edu (Chris Hall) writes:

>This was the best I could get it down to; it's 49 bytes long.

>width equ 80 ;width used; 160 bytes/line still assumed
>height equ 25 ;height to use
>ball equ 'O' ;character for the ball

>main:
> mov ah,0b8 ;al=0 **PROVIDED** no command-line params!
> mov es,ax ;es=screen segment
> xor di,di ;start at origin of screen
> mov bl,162 ;offset to next position (bx=0 for .COM file)
> mov dx,(width-1) by (height-1);no. of columns (dh)/rows (dl) left

"xor di,di" could be replaced by "pop di" for a .com file and thus saving
one byte. Is Bx=0 officially ensured for a .com file?

Morten Welinder
te...@diku.dk
--
-------------------------------------------------------------------------
Visit the lyrics archive at ftp.uwp.edu (mirrored to nic.funet.fi, a site
in Finland). All kinds of lyrics available -- upload "yours" and join.
-------------------------------------------Morten Welinder, te...@diku.dk

Alan Raskin

unread,
May 31, 1993, 11:37:09 PM5/31/93
to
In <1993May31.1...@odin.diku.dk> te...@diku.dk (Morten Welinder) writes:

>cah...@nyx.cs.du.edu (Chris Hall) writes:

>>This was the best I could get it down to; it's 49 bytes long.

>>width equ 80 ;width used; 160 bytes/line still assumed
>>height equ 25 ;height to use
>>ball equ 'O' ;character for the ball

>>main:
>> mov ah,0b8 ;al=0 **PROVIDED** no command-line params!
>> mov es,ax ;es=screen segment
>> xor di,di ;start at origin of screen
>> mov bl,162 ;offset to next position (bx=0 for .COM file)
>> mov dx,(width-1) by (height-1);no. of columns (dh)/rows (dl) left

>"xor di,di" could be replaced by "pop di" for a .com file and thus saving
>one byte. Is Bx=0 officially ensured for a .com file?

Don't know about whether BX=0 is guaranteed, but it seems to be true.
However, doing the "pop di" is a very good way to lock up the computer
when the program terminates; did the original poster require a well-
behaved program (as well as being short :-)?

And how about correctness? It turns out that if you let the program run
long enough, the ball eventually reaches the lower left corner of the
screen and is eaten by a black hole. Chris Hall tried to finesse things
by using the same "xor" for both the change in x- and y-directions;
however, at the corners, the "xor" has to be done *twice*. What's
interesting is that if you fix the logic, the program is still only 49
bytes long; the correct code is given below. Enjoy!

-Alan

;
; 49-byte code to display a ball bouncing off the edges of the screen. The
; logic and first version originated with Chris Hall (cah...@nyx.cs.du.edu);
; however, it did not handle corners correctly, requiring a simple
; modification of the code by Alan Raskin (ras...@fafner.physics.umanitoba.ca)
; which amazingly did *not* increase the size of the executable.
;

code SEGMENT PARA PUBLIC 'Code'
ASSUME cs:CODE, ds:CODE

ORG 100h

wwidth EQU 80 ; width used; 2 bytes/character assumed
height EQU 25 ; height used
ball EQU 001 ; character for the ball (happy face)

start:
mov ah, 0b8h ; 2 - AL=0 if no command-line parameters?
mov es, ax ; 2 - ES=screen segment
xor di, di ; 2 - start at origin of screen
mov bl, 2*(wwidth+1) ; 2 - offset to next position (BX=0 for
; .COM file?)
mov dx, (wwidth-1)*256+(height-1)
; 3 - # of columns (DH) & rows (DL) left
; before change in direction
l0:
mov al, ball ; 2 - load ball character
xchg es:[di], al ; 1+2 - get original character, and
; store ball on screen
loop $ ; 2 - delay (CX=0 at start of .COM file)
stosb ; 1 - store original character back
lea di, [di+bx-1] ; 3 - DI+BX-1=next screen position

dec dh ; 2 - decrement column count
jnz l1 ; 2 - another column -- don't swap x yet

; for a bounce off of the left or right side of the screen, BX changes in
; magnitude from 162 to 158 (or vice versa) with no change of sign; this is
; accomplished by an exclusive or:
;
; 162 = 1010 0010
; 158 = 1001 1110
; 3Ch = 0011 1100

mov dh, wwidth-1 ; 2 - reset column count
xor bl, 3Ch ; 3 - swap x-direction
l1:
dec dl ; 2 - decrement row count
jnz l2 ; 2 - another row -- don't swap y yet

; for a bounce off of the bottom or top of the screen, BX changes in magnitude
; as before, but also changes in sign

mov dl, height-1 ; 2 - reset row count
neg bx ; 2 - start to swap y-direction...
xor bl, 3Ch ; 3 - done!

l2: ; jump to here to check if key
; has been pressed
mov ah, 01h ; 2 - load fcn. # for Get Keyboard Status
int 16h ; 2 - call keyboard interrupt
jz l0 ; 2 - if key not pressed, repeat
ret ; 1 - otherwise exit

code ENDS
END start

Stefan Wessels

unread,
Jun 1, 1993, 12:45:45 PM6/1/93
to
2 Versions included. Both use the cursor for a ball. The second version
does not exactly stick to the rules for borders, as it just checks for
the right hand side of the screen. This locates the cursor to a position
that is not correct. The second version uses self-modifying (sp?) code, but
I still like it.

Version 1 : 42 Bytes
Version 2 : 37 Bytes

Version 1
----------

code segment para 'code'
org 100h
assume cs:code,ds:code,ss:code
begin:
xor dx, dx
mov bl,01h ; Col inc
mov ax,0201h ; ah = Set Cursor, Al = Row inc

Main: add dl,bl ; Cols inc/dec
jz Wrap ; Left hand side of screen?
cmp dl,79 ; Right hand side of screen
jne NoWrap ; Nope
Wrap: neg bl ; Swop direction

NoWrap: add dh,al ; Rows inc/dec
jz RWrap ; Top of screen? Zero=y=swop dir
cmp dh,24 ; Bottom?
jne NoRWrap ; no
RWrap: neg al ; swop direction

NoRWrap:
int 10h ; position cursor
Delay: loop Delay ; delay to make visable
push ax
in al,60h ; read keyboard controller
cmp al,1 ; ah = 1 = ESC key pressed
pop ax
jnz Main ; ah <> 1 - Continue
ret ; return to DOS

code ends
end begin


Version 2
----------
; code by Rudi Engelbrecht
;
CODE_SEG SEGMENT PARA 'Code'
ASSUME CS:CODE_SEG

ORG 100h

Toets PROC NEAR
mov bx, 0008h
mov dx, bx
STARTLOOP:
mov di, offset MODIFY+1

cmp dh, 24
jb @@99
NEXT:
xor byte ptr [di], bl
@@99:
TEMPLOOP: loop TEMPLOOP

MODIFY:
inc dh
inc dx
inc di

mov ah, 02h

int 10h

cmp dl, 4Eh
ja NEXT

; Get keyboard character
KEYBOARD:
mov ah, 01h
int 16h
jz STARTLOOP
ret
Toets ENDP

EINDE:

CODE_SEG ENDS
END Toets

0 new messages