Dec 052017
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
jg@65
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