Tuesday, November 20, 2007

IBM PC Assembly Language Tutorial 1

IBM PC Assembly Language Tutorial 1

Why Learn Assembler?

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 compiling 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 operating 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 responsibility 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 keyboard 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 assembler 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 languages 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.

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; given 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 assembler 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..

No comments: