Dec 052017
 
Defender-type game with ASM and C source. This source code is supposed to be a primer for ASM begineers.
File DEFEND.ZIP from The Programmer’s Corner in
Category Assembly Language
Defender-type game with ASM and C source. This source code is supposed to be a primer for ASM begineers.
File Name File Size Zip Size Zip Type
BYTE.LBM 292 121 deflated
EBACKS.ASM 28628 5490 deflated
EBACKS.OBJ 3450 2317 deflated
EGA.EQU 2124 830 deflated
EGA.MAK 346 157 deflated
EGACSET.INC 3336 678 deflated
EGAMODE.ASM 17733 4320 deflated
EGAMODE.OBJ 2028 1446 deflated
EGAMODE.OVL 5037 2966 deflated
EGATOOLS.C 3643 1169 deflated
EGATOOLS.H 3457 1136 deflated
EGATOOLS.OBJ 2940 1862 deflated
ESPRITE.ASM 12766 3546 deflated
ESPRITE.OBJ 1657 1053 deflated
FIRE.LBM 340 178 deflated
FIRE1.DAT 7 7 stored
FIRE1.E16 266 113 deflated
FIRE1.LBM 1920 173 deflated
FIRE2.DAT 7 7 stored
FIRE2.E16 326 126 deflated
FIRE2.LBM 1942 179 deflated
FIRE3.DAT 7 7 stored
FIRE3.E16 266 110 deflated
FIRE3.LBM 1928 171 deflated
FIRE4.DAT 7 7 stored
FIRE4.E16 326 106 deflated
FIRE4.LBM 1924 171 deflated
FIREL1.DAT 8 8 stored
FIREL1.E16 266 109 deflated
FIREL1.LBM 1926 169 deflated
FIREL2.DAT 8 8 stored
FIREL2.E16 326 129 deflated
FIREL2.LBM 1956 185 deflated
FIREL3.DAT 8 8 stored
FIREL3.E16 266 110 deflated
FIREL3.LBM 1942 176 deflated
FIREL4.DAT 8 8 stored
FIREL4.E16 426 114 deflated
FIREL4.LBM 1940 183 deflated
GAME.ASM 19960 4434 deflated
GAME.MAK 167 103 deflated
GAME.OBJ 2132 1340 deflated
GAME.OVL 1783 841 deflated
GLOBAL.EQU 3485 1144 deflated
KEYS.ASM 4449 1368 deflated
KEYS.OBJ 1619 1051 deflated
LAND1.S16 235 118 deflated
LAND2.S16 292 171 deflated
LAND3.S16 309 178 deflated
LAND4.S16 245 133 deflated
M.BAT 12 12 stored
MAIN.ASM 19692 5565 deflated
MAIN.EXE 8249 4031 deflated
MAIN.MAK 136 93 deflated
MAIN.OBJ 6276 3903 deflated
MOUNT.LBM 3552 925 deflated
OVERVIEW.DOC 8692 3453 deflated
PLANEL.DAT 8 8 stored
PLANEL.E16 2586 456 deflated
PLANEL.LBM 2224 293 deflated
PLANER.DAT 8 8 stored
PLANER.E16 2586 470 deflated
PLANER.LBM 2210 299 deflated
PLANER.TBL 134 81 deflated
SCREEN16.INC 413 168 deflated
SHOWLBM.C 6630 2036 deflated
SHOWLBM.EXE 34523 19168 deflated
SHOWLBM.H 1192 468 deflated
SHOWLBM.OBJ 5433 3213 deflated
SHOWLBM.PRJ 62 43 deflated
SHOWLBM.TC 1690 372 deflated
SPAM.C 14914 4346 deflated
SPAM.EXE 85273 22599 deflated
SPAM.H 949 407 deflated
SPAM.OBJ 11641 6687 deflated
SPAM.PRJ 33 28 deflated
SPAM.TC 1690 370 deflated
SPRITE16.INC 439 137 deflated
STAMP16.INC 81 49 deflated
TITLE.LBM 3730 827 deflated
TITLE.S16 2522 661 deflated
TITLE1.S16 2522 657 deflated
TOOLS.ASM 31613 6505 deflated
TOOLS.DOC 12984 5078 deflated
TOOLS.EQU 1890 773 deflated
TOOLS.OBJ 9844 5803 deflated
TPCREAD.ME 199 165 deflated

Download File DEFEND.ZIP Here

Contents of the OVERVIEW.DOC file



A while back I caught the tail end of a discussion on the Borland RT
about learning how to program in Assembler. I got the impression that many
people think that programming in Assembler is very difficult to do.

Although programming in Assembler isn't exactly the same as programming
in C they do share a lot of the same concepts and the most difficult part of
programming, defining the problem, has to be done for either language before
a solution can be implemented.

A large portion of a program's code involves making decisions or moving
data around from point A to point B. Pretty simple stuff - even in assembler.

EXAMPLE:

These C statements

inta,b;
a = 10;
b = a;
if (a == b)
b = 20;

do the same as these assembler statements.

adw?;int a,b
bdw?

mov[a],10;a = 10

movax,[a];b = a
mov[b],ax

movax,[a];if (a == b)
cmpax,[b]
jneskip

mov[b],20;b = 20
skip:
.
.
.


If assembler and C both do the same thing why bother to learn
assembler ?

Even with the excellent compilers available today there are times
when the compiler does not generate the most efficient code possible. For
the majority of the time that would not be a problem - but some types of
applications (real time process control, arcade games, etc.) may need every
last ounce of performance that can be squeezed out of the processor.

To illustrate this I compiled spam.c (one of the files in this archive)
at the command line using the following parameters:

tcc -S -r -O -d -mc -Z -G spam.c


The C code routine that we are examining is move_ega.

char *move_ega(unsigned char *d, unsigned char *s)
{
int i, *d1, *s1;

(char *)d1 = d;
(char *)s1 = s;

*d1++ = *s1++;/* rows */
*d1++ = *s1++;/* columns*/
i = *s1;/* size */
*d1++ = *s1++;

d = (char *)d1;
s = (char *)s1;

for ( ; i>0; *d++ = *s++, --i);
return(d);
}


The assembler output for the code (after removing the '?debug' lines
and adding comments) was as follows:

_move_egaprocnear

pushbp
movbp,sp
subsp,8;reserve s1 & d1 storage
pushsi

lesbx,dword ptr [bp+4];d1 = d
movword ptr [bp-6],es
movword ptr [bp-8],bx

lesbx,dword ptr [bp+8];s1 = s
movword ptr [bp-2],es
movword ptr [bp-4],bx

movax,word ptr es:[bx];*d1++ = *s1++
lesbx,dword ptr [bp-8]
movword ptr es:[bx],ax
addword ptr [bp-4],2
addword ptr [bp-8],2

lesbx,dword ptr [bp-4];*d1++ = *s1++
movax,word ptr es:[bx]
lesbx,dword ptr [bp-8]
movword ptr es:[bx],ax
addword ptr [bp-4],2
addword ptr [bp-8],2

lesbx,dword ptr [bp-4];i = *s1
movsi,word ptr es:[bx]

movax,word ptr es:[bx];*d1++ = *s1++
lesbx,dword ptr [bp-8]
movword ptr es:[bx],ax
addword ptr [bp-4],2
addword ptr [bp-8],2

movbx,word ptr [bp-8];d = d1
movword ptr [bp+6],es
movword ptr [bp+4],bx
lesbx,dword ptr [bp-4];s = s1
movword ptr [bp+10],es
movword ptr [bp+8],bx
jmpshort @66
@65:
lesbx,dword ptr [bp+8];*d++ = *s++
moval,byte ptr es:[bx]
lesbx,dword ptr [bp+4]
movbyte ptr es:[bx],al
incword ptr [bp+8]
incword ptr [bp+4]
decsi;--i
@66:
orsi,si;i>0
[email protected]

movdx,word ptr [bp+6];return(d)
movax,word ptr [bp+4]
popsi
movsp,bp
popbp
ret

_move_egaendp


The same function (in tools.asm) was written in assembler as follows:

ega_moveprocnear
publicega_move

argega_ptr:ptr, buff:ptr

push ds
push es
pushsi
pushdi

lesdi,[ega_ptr]; (d1 = d)
ldssi,[buff];input buffer (s1 = s)
cld
movsw;rows (*d1++ = *s1++)
movsw;screen byte columns (*d1++ = *s1++)
lodsw;data count (i = *si)
stosw (*d1++ = *s1++)

movcx,ax; (for loop)
rep movsb

movax,di; (return(d))
mov dx,es
ega_move_xit:
popdi
popsi
pop es
pop ds
ret

ega_moveendp


The compiler has to translate the C statements by selecting
sequences of Assembler instructions that will perform the desired task. It
has to do this without knowing the overall purpose of the function. Not an
easy task.

On the other hand, a programmer working in Assembler can make
judgments and decisions based on the context of the code that a compiler
would find very difficult to do. This doesn't mean that compilers always
make bad decisions when selecting instructions or that programmers always make
good ones - I'm just trying to point out that if you need maximum efficiency
in sections of your code then you may want to re-write those sections in
Assembler.

To learn any programming language you need to learn about the tools
that the language has to offer (keywords, directives, etc.). This is also true
with Assembler, but when you learn Assembler you also need to learn about the
hardware (the micro-processor, video, keyboard, operating environment, etc.).

There are many good books available on 80x86 Assembler programming that
will help you to learn the instruction set and memory addressing modes. A
shareware program called LW86 is a pretty good POP UP reference for the
instruction set or you could buy Nortons Guides for Assembler which is also
very good.

If you are currently programming in C then you probably already have a
book or two on the DOS environment. You will also need to get some books that
cover the BIOS and hardware that you may want to control directly.

As with C programming you won't learn everything overnight. It takes a
lot of practice to learn any language and Assembler is no exception. In the
long run I think that you will find that it is worth the effort. Besides
allowing you to write faster, smaller programs you will find that the things
you learn programming in Assembler will have a positive effect on your C
programming efforts.


To demonstrate some assembler programming I put together a few routines
that can be used to develop a real time arcade style game (it could be turned
into a DEFENDER type game without too much trouble).

It is divided into several parts.

To help develop graphics for the game there are

spam.c, spam.h used for creating sprite data
showlbm.c, showlbm.h used for creating screens and objects.

Both of these use
egatools.c, egatools.h
tools.asm, tools.equ

The game portion is divided into

main.asm, menu picker, overlay manager,
keys.asm general startup/exit housekeeping

egamode.asm, screen/sprite handler overlay for
esprite.asm, ega mode 13 (320x200 16 color)
ebacks.asm

game.asm game play logic overlay

These use
global.equ
ega.equ
screen16.inc
sprite16.inc
stamp16.inc

There are also some graphics files (rather crude because I'm not
an artist).

The *.lbm files were created using Deluxe Paint II and are the files
used by SHOWLBM and SPAM to generate the final graphics files.

The *.s16 files are the title screen and landscape files (generated
by showlbm.

The *.e16 files are the sprite files generated by spam.

The *.dat are files used by spam to find the source (*.lbm) files
used to generate the sprite files.


The graphics tools (spam & showlbm) were originaly written entirely
in Assembler and were typical programmer tools - pieced together from a bunch
of different projects,no comments, and hacked up pretty bad. I re-wrote
portions of them in Turbo C and reformatted the assembler parts to take
advantage of the C parameter passing features in Turbo Assembler. I also
added comments though they are still rather sparse.

The idea behind using C and assembler was to show how easy it is to
use assembler functions with C. TASM takes care of most of the SEGMENT
problems and lets you concentrate on the functions.

See TOOLS.DOC for more information on the graphics tools.


The Game portions (main, mode overlay, game overlay) are written in
Assembler and demonstrate how to manage SEGMENTS, OVERLAYS, VIRTUAL SCREENS,
GRAPHICS COMPRESSION/DECOMPRESSION, INTERRUPT PROCESSING, etc.

Most of the routines are not horribly complicated, but if you are new
to assembler programming you will probably have to spend some time studying
them to understand what they are doing.

I hope that you find the things in this archive useful and that you
don't find assembler programming too frustrating.

Have fun,

Larry Ashmun (L.ASHMUN)



 December 5, 2017  Add comments

Leave a Reply