The reasons for LEARNING assembler are not the same as the reasons for
USING it in a particular application. But, we have to start with some of
the reasons for using it and then I think the reasons for learning it will
become clear.
First, let's dispose of a bad reason for using it. Don't use it just
because you think it is going to execute faster. A particular sequence of
ordinary bread-and-butter computations written in PASCAL, C, FORTRAN, or
compiled BASIC can do the job just about as fast as the same algorithm
coded in assembler. Of course, interpretive BASIC is slower, but if you
have a BASIC application which runs too slow you probably want to try com-
IBM PC Assembly Language Tutorial 1
piling it before you think too much about translating parts of it to
another language.
On the other hand, high level languages do tend to isolate you from the
machine. That is both their strength and their weakness. Usually, when
implemented on a micro, a high level language provides an escape mechanism
to the underlying operating system or to the bare machine. So, for
example, BASIC has its PEEK and POKE. But, the route to the bare machine
is often a circuitous one, leading to tricky programming which is hard to
follow.
For those of us working on PC's connected to SHARE-class mainframes, we are
generally concerned with three interfaces: the keyboard, the screen, and
the communication line or lines. All three of these entities raise machine
dependent issues which are imperfectly addressed by the underlying operat-
ing system or by high level languages.
Sometimes, the system or the language does too little for you. For
example, with the asynch adapter, the system provides no interrupt handler,
no buffer, and no flow control. The application is stuck with the respon-
sibility for monitoring that port and not missing any characters, then
deciding what to do with all errors. BASIC does a reasonable job on some
of this, but that is only BASIC. Most other languages do less.
Sometimes, the system may do too much for you. System support for the key-
board is an example. At the hardware level, all 83 keys on the keyboard
send unique codes when they are pressed, held down, and released. But,
someone has decided that certain keys, like Num Lock and Scroll Lock are
going to do certain things before the application even sees them and can't
therefore be used as ordinary keys.
Sometimes, the system does about the right amount of stuff but does it less
efficiently then it should. System support for the screen is in this
class. If you use only the official interface to the screen you sometimes
slow your application down unacceptably. I said before, don't use assem-
bler just to speed things up, but there I was talking about mainline code,
which generally can't be speeded up much by assembler coding. A critical
system interface is a different matter: sometimes we may have to use
assembler to bypass a hopelessly inefficient implementation. We don't want
to do this if we can avoid it, but sometimes we can't.
Assembly language code can overcome these deficiencies. In some cases, you
can also overcome these deficiencies by judicious use of the escape valves
which your high level language provides. In BASIC, you can PEEK and POKE
and INP and OUT your way around a great many issues. In many other lan-
guages you can issue system calls and interrupts and usually manage, one
way or other, to modify system memory. Writing handlers to take real-time
hardware interrupts from the keyboard or asynch port, though, is still
going to be a problem in most languages. Some languages claim to let you
do it but I have yet to see an acceptably clean implementation done that
way.
The real reason while assembler is better than "tricky POKEs" for writing
machine-dependent code, though, is the same reason why PASCAL is better
than assembler for writing a payroll package: it is easier to maintain.
IBM PC Assembly Language Tutorial 2
Let the high level language do what it does best, but recognize that there
are some things which are best done in assembler code. The assembler,
unlike the tricky POKE, can make judicious use of equates, macros, labels,
and appropriately placed comments to show what is really going on in this
machine-dependent realm where it thrives.
So, there are times when it becomes appropriate to write in assembler; giv-
en that, if you are a responsible programmer or manager, you will want to
be "assembler-literate" so you can decide when assembler code should be
written.
What do I mean by "assembler-literate?" I don't just mean understanding
the 8086 architecture; I think, even if you don't write much assembler code
yourself, you ought to understand the actual process of turning out assem-
bler code and the various ways to incorporate it into an application. You
ought to be able to tell good assembler code from bad, and appropriate
assembler code from inappropriate.
Steps to becoming ASSEMBLER-LITERATE____________________________________Steps to becoming ASSEMBLER-LITERATESteps to becoming ASSEMBLER-LITERATESteps to becoming ASSEMBLER-LITERATE
1. Learn the 8086 architecture and most of the instruction set. Learn
what you need to know and ignore what you don't. Reading: The 8086
Primer by Stephen Morse, published by Hayden. You need to read only
two chapters, the one on machine organization and the one on the
instruction set.
2. Learn about a few simple DOS function calls. Know what services the
operating system provides. If appropriate, learn a little about other
systems too. It will aid portability later on. Reading: appendices D
and E of the PC DOS manual.
3. Learn enough about the MACRO assembler and the LINKer to write some
simple things that really work. Here, too, the main thing is figuring
out what you don't need to know. Whatever you do, don't study the sam-
ple programs distributed with the assembler unless you have nothing
better!
4. At the same time as you are learning the assembler itself, you will
need to learn a few tools and concepts to properly combine your assem-
bler code with the other things you do. If you plan to call assembler
subroutines from a high level language, you will need to study the
interface notes provided in your language manual. Usually, this forms
an appendix of some sort. If you plan to package your assembler rou-
tines as .COM programs you will need to learn to do this. You should
also learn to use DEBUG.
5. Read the Technical Reference, but very selectively. The most important
things to know are the header comments in the BIOS listing. Next, you
will want to learn about the RS 232 port and maybe about the video
adapters.
IBM PC Assembly Language Tutorial 3
Notice that the key thing in all five phases is being selective. It is
easy to conclude that there is too much to learn unless you can throw away
what you don't need. Most of the rest of this talk is going to deal with
this very important question of what you need and don't need to learn in
each phase. In some cases, I will have to leave you to do almost all of
the learning, in others, I will teach a few salient points, enough, I hope,
to get you started. I hope you understand that all I can do in an hour is
get you started on the way.
Phase 1: Learn the architecture and instruction set____________________________________________________Phase 1: Learn the architecture and instruction setPhase 1: Learn the architecture and instruction setPhase 1: Learn the architecture and instruction set
The Morse book might seem like a lot of book to buy for just two really
important chapters; other books devote a lot more space to the instruction
set and give you a big beautiful reference page on each instruction. And,
some of the other things in the Morse book, although interesting, really
aren't very vital and are covered too sketchily to be of any real help.
The reason I like the Morse book is that you can just read it; it has a
very conversational style, it is very lucid, it tells you what you really
need to know, and a little bit more which is by way of background; because
nothing really gets belabored to much, you can gracefully forget the things
you don't use. And, I very much recommend READING Morse rather than study-
ing it. Get the big picture at this point.
Now, you want to concentrate on those things which are worth fixing in mem-
ory. After you read Morse, you should relate what you have learned to this
outline.
1. You want to fix in your mind the idea of the four segment registers
CODE, DATA, STACK, and EXTRA. This part is pretty easy to grasp. The
8086 and the 8088 use 20 bit addresses for memory, meaning that they
can address up to 1 megabyte of memory. But, the registers and the
address fields in all the instructions are no more that 16 bits long.
So, how to address all of that memory? Their solution is to put
together two 16 bit quantities like this:
calculation SSSS0 ---- value in the relevant segment register SHL 4
depicted in AAAA ---- apparent address from register or instruction
hexadecimal --------
RRRRR ---- real address placed on address bus
In other words, any time memory is accessed, your program will supply a
sixteen bit address. Another sixteen bit address is acquired from a
segment register, left shifted four bits (one nibble) and added to it
to form the real address. You can control the values in the segment
registers and thus access any part of memory you want. But the segment
registers are specialized: one for code, one for most data accesses,
one for the stack (which we'll mention again) and one "extra" one for
additional data accesses.
Most people, when they first learn about this addressing scheme become
obsessed with converting everything to real 20 bit addresses. After a
while, though, you get use to thinking in segment/offset form. You
IBM PC Assembly Language Tutorial 4
tend to get your segment registers set up at the beginning of the pro-
gram, change them as little as possible, and think just in terms of
symbolic locations in your program, as with any assembly language.
EXAMPLE:
MOV AX,DATASEG
MOV DS,AX ;Set value of Data segment
ASSUME DS:DATASEG ;Tell assembler DS is usable
.......
MOV AX,PLACE ;Access storage symbolically by 16 bit address
In the above example, the assembler knows that no special issues are
involved because the machine generally uses the DS register to complete
a normal data reference.
If you had used ES instead of DS in the above example, the assembler
would have known what to do, also. In front of the MOV instruction
which accessed the location PLACE, it would have placed the ES segment
prefix. This would tell the machine that ES should be used, instead of
DS, to complete the address.
Some conventions make it especially easy to forget about segment regis-
ters. For example, any program of the COM type gets control with all
four segment registers containing the same value. This program exe-
cutes in a simplified 64K address space. You can go outside this
address space if you want but you don't have to.
2. You will want to learn what other registers are available and learn